Content deleted Content added
(bot/CD) |
(bot/CD) |
||
Line 351:
var version = "0.8.0";
var gitAbbrevHash = "
var gitBranch = "
var gitDate = "
var gitVersion = "0.8.0+
/**
Line 855:
}
});
}
}
Line 977 ⟶ 945:
/**
*
*
* @param array The array to get the last element from
* @return The last element of the array
*/
function
}
/**
* Each WikiHeadingType implies specific fields in {@link WikiHeading}:
*
* - `PARSOID` implies that there is no headline element, and that the `h`
* element is the root heading element. This means `h.innerText` will be
* "Section title".
* - `OLD` implies that there is a headline element and possibly an editsection
* element, and that the `h` is the root heading element. This means that
* `h.innerText` will be "Section title[edit | edit source]" or similar.
* - `NEW` implies that there is a headline element and possibly an editsection
* element, and that a `div` is the root heading element. This means that
* `h.innerText` will be "Section title".
*/
var WikiHeadingType;
(function (WikiHeadingType) {
WikiHeadingType[WikiHeadingType["PARSOID"] = 0] = "PARSOID";
WikiHeadingType[WikiHeadingType["OLD"] = 1] = "OLD";
WikiHeadingType[WikiHeadingType["NEW"] = 2] = "NEW";
})(WikiHeadingType || (WikiHeadingType = {}));
/**
* Get relevant information from an H* element in a section heading.
*
* @param
* @return
*/
function
return {
h: headingElement,
id: headingElement.id,
title: headingElement.innerText,
level: +last(headingElement.tagName)
};
}
/**
* Annoyingly, there are many different ways that a heading can be parsed
* into depending on the version and the parser used for given wikitext.
*
* In order to properly perform such wiki heading checks, we need to identify
*
* if so.
*
* Since this function needs to check many things before deciding if a given
* HTML element is part of a section heading or not, this also acts as an
* `isWikiHeading` check.
*
* The layout for a heading differs depending on the MediaWiki version:
*
* <b>On 1.43+ (Parser)</b>
* ```html
* <div class="mw-heading mw-heading2">
* <h2 id="Parsed_wikitext...">Parsed <i>wikitext</i>...</h2>
* <span class="mw-editsection>...</span>
* </div>
* ```
*
* <b>On Parsoid</b>
* ```html
* <h2 id="Parsed_wikitext...">Parsed <i>wikitext</i>...</h2>
* ```
*
* <b>On pre-1.43</b>
* ```html
* <h2>
* <span class="mw-headline" id="Parsed_wikitext...">Parsed <i>wikitext</i>...</span>
* <span class="mw-editsection">...</span>
* </h2>
* ```
*
* <b>Worst case execution time</b> would be if this was run with an element which was
* outside a heading and deeply nested within the page.
*
* Backwards-compatibility support may be removed in the future. This function does not
* support Parsoid specification versions lower than 2.0.
*
* @param node The node to check for
* @param ceiling An element which `node` must be in to be a valid heading.
* This is set to the `.mw-parser-output` element by default.
* @return The root heading element (can be an <h2> or <div>),
* or `null` if it is not a valid heading.
*/
function
if (node == null) {
// Not valid input, obviously.
return null;
}
const rootNode = node.getRootNode();
// Break out of text nodes until we hit an element node.
while (node.nodeType !== node.ELEMENT_NODE) {
node = node.parentNode;
if (node === rootNode) {
// We've gone too far and hit the root. This is not a wiki heading.
return null;
}
}
// node is now surely an element.
let elementNode = node;
// If this node is the 1.43+ heading root, return it immediately.
if (elementNode.classList.contains('mw-heading')) {
return Object.assign({ type: WikiHeadingType.NEW, root: elementNode }, getHeadingElementInfo(Array.from(elementNode.children)
.find(v => /^H[123456]$/.test(v.tagName))));
}
// Otherwise, we're either inside or outside a mw-heading.
// To determine if we are inside or outside, we keep climbing up until
// we either hit an <hN> or a given stop point.
// The stop point is, by default, `.mw-parser-output`, which exists both in a
// Parsoid document and in standard parser output. If such an element doesn't
// exist in this document, we just stop at the root element.
ceiling = (_a = ceiling !== null && ceiling !== void 0 ? ceiling : elementNode.ownerDocument.querySelector('.mw-parser-output')) !== null && _a !== void 0 ? _a : elementNode.ownerDocument.documentElement;
// While we haven't hit a heading, keep going up.
while (elementNode !== ceiling) {
if (/^H[123456]$/.test(elementNode.tagName)) {
// This element is a heading!
// Now determine if this is a MediaWiki heading.
if (elementNode.parentElement.classList.contains('mw-heading')) {
// This element's parent is a `div.mw-heading`!
return Object.assign({ type: WikiHeadingType.NEW, root: elementNode.parentElement }, getHeadingElementInfo(elementNode));
}
else {
const headline = elementNode.querySelector(':scope > .mw-headline');
if (headline != null) {
// This element has a `.mw-headline` child!
return {
type: WikiHeadingType.OLD,
root: elementNode,
h: elementNode,
id: headline.id,
title: headline.innerText,
level: +last(elementNode.tagName)
};
}
else if (elementNode.parentElement.tagName === 'SECTION' &&
elementNode.parentElement.firstElementChild === elementNode) {
// A <section> element is directly above this element, and it is the
// first element of that section!
// This is a specific format followed by the 2.8.0 MediaWiki Parsoid spec.
// https://www.mediawiki.org/wiki/Specs/HTML/2.8.0#Headings_and_Sections
return {
type: WikiHeadingType.PARSOID,
root: elementNode,
h: elementNode,
id: elementNode.id,
title: elementNode.innerText,
level: +last(elementNode.tagName)
};
}
else {
// This is a heading, but we can't figure out how it works.
// This usually means something inserted an <h2> into the DOM, and we
// accidentally picked it up.
// In that case, discard it.
return null;
}
}
}
else if (elementNode.classList.contains('mw-heading')) {
// This element is the `div.mw-heading`!
// This usually happens when we selected an element from inside the
// `span.mw-editsection` span.
return Object.assign({ type: WikiHeadingType.NEW, root: elementNode }, getHeadingElementInfo(Array.from(elementNode.children)
.find(v => /^H[123456]$/.test(v.tagName))));
}
else {
// Haven't reached the top part of a heading yet, or we are not
// in a heading. Keep climbing up the tree until we hit the ceiling.
elementNode = elementNode.parentElement;
}
}
// We hit the ceiling. This is not a wiki heading.
return null;
}
/**
*
*
* Alias for `normalizeWikiHeading( el ) != null`.
*
* @param el The element to check
* @return
*/
function
return normalizeWikiHeading(el) != null;
}
Line 1,123 ⟶ 1,227:
return false;
}
el
// eslint-disable-next-line security/detect-non-literal-regexp
new RegExp(window.deputy.wikiConfig.cci.headingMatch.get()).test(
}
/**
Line 1,139 ⟶ 1,239:
* @return The <h*> element of the heading.
*/
return this.findContributionSurveyHeadings()[0];
}
Line 1,151 ⟶ 1,251:
*/
findContributionSurveyHeading(sectionIdentifier, useId = false) {
return this.findContributionSurveyHeadings()
.find((v) => normalizeWikiHeading(v)[useId ? 'id' : 'title'] === sectionIdentifier);
}
/**
Line 1,177 ⟶ 1,273:
.filter((h) => this.isContributionSurveyHeading(h));
}
}
/**
Line 1,218 ⟶ 1,290:
*/
getContributionSurveySection(sectionHeading) {
return getSectionElements(heading.root, (el) => { var _a, _b; return heading.level >= ((_b = (_a = normalizeWikiHeading(el, ceiling)) === null || _a === void 0 ? void 0 : _a.level) !== null && _b !== void 0 ? _b : Infinity); });
}
/**
Line 1,379 ⟶ 1,449:
h_1("a", { onClick: () => __awaiter(this, void 0, void 0, function* () {
if (casePage && casePage.lastActiveSections.length > 0) {
const headingId =
if (window.deputy.config.cci.openOldOnContinue.get()) {
if (casePage.lastActiveSections.indexOf(headingId) === -1) {
Line 1,391 ⟶ 1,461:
}
else {
yield window.deputy.session.DeputyRootSession.startSession(heading.h);
}
}) }, mw.message(casePage && casePage.lastActiveSections.length > 0 ?
Line 1,408 ⟶ 1,478:
var _a;
return (_a = element === null || element === void 0 ? void 0 : element.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(element);
}
/**
* Log errors to the console.
*
* @param {...any} data
*/
function error(...data) {
console.error('[Deputy]', ...data);
}
Line 6,375 ⟶ 6,454:
*
* @param heading The heading to check
* @return The n, a number
*/
function sectionHeadingN
try {
const headingNameEndPattern = /(?:\s|_)(\d+)/g;
const headingIdEndPattern = /_(\d+)/g;
const headingId =
const headingIdMatches = headingId.match(headingIdEndPattern);
const headingNameMatches =
if (headingIdMatches == null) {
return 1;
Line 6,434 ⟶ 6,512:
constructor(casePage, heading) {
this.casePage = casePage;
this.heading =
this.sectionNodes = casePage.getContributionSurveySection(heading);
}
Line 6,609 ⟶ 6,687:
*/
get headingName() {
return
}
/**
Line 6,615 ⟶ 6,693:
*/
get headingN() {
return sectionHeadingN(this.heading
}
/**
Line 6,770 ⟶ 6,848:
toggleSectionElements(toggle) {
var _a;
const bottom = (_a = this.heading.root.nextSibling) !== null && _a !== void 0 ? _a : null;
for (const sectionElement of this.sectionNodes) {
if (toggle) {
this.heading.root.parentNode.insertBefore(sectionElement, bottom);
}
else {
Line 6,938 ⟶ 7,016:
// Remove whatever section elements are still there.
// They may have been greatly modified by the save.
const sectionElements = this.casePage.getContributionSurveySection(this.heading.root);
sectionElements.forEach((el) => removeElement(el));
// Clear out section elements and re-append new ones to the DOM.
this.sectionNodes = [];
// Heading is preserved to avoid messing with IDs.
const heading = this.heading.root;
const insertRef = (_a = heading.nextSibling) !== null && _a !== void 0 ? _a : null;
for (const child of Array.from(element.childNodes)) {
Line 6,957 ⟶ 7,035:
yield this.getSection(Object.assign(wikitext, { revid }));
yield this.prepare();
// Run this asynchronously.
setTimeout(this.loadData.bind(this), 0);
Line 7,166 ⟶ 7,237:
casePage.findContributionSurveyHeadings()
.forEach((heading) => {
const
const link = DeputyCCISessionStartLink(normalizedHeading, casePage);
startLink.push(link);
});
window.deputy.comms.addEventListener('sessionStarted', () => {
Line 7,189 ⟶ 7,261:
return __awaiter(this, void 0, void 0, function* () {
yield mw.loader.using(['oojs-ui-core', 'oojs-ui.styles.icons-content'], () => {
const firstHeading = casePage.
if (firstHeading) {
const stopButton = new OO.ui.ButtonWidget({
Line 7,223 ⟶ 7,295:
window.deputy.session.init();
});
}
});
Line 7,242 ⟶ 7,314:
mw.loader.using(['oojs-ui-core', 'oojs-ui.styles.icons-content'], () => {
const lastActiveSection = DeputyRootSession.findFirstLastActiveSection(casePage);
const firstSection =
// Insert element directly into widget (not as text, or else event
// handlers will be destroyed).
Line 7,259 ⟶ 7,331:
'deputy.session.continue.help' :
'deputy.session.continue.help.fromStart', lastActiveSection ?
casePage.lastActiveSections[0]
.replace(/_/g, ' '),
actions: [continueButton],
closable: true
Line 7,276 ⟶ 7,348:
else {
DeputyRootSession.continueSession(casePage, [
]);
}
window.deputy.comms.removeEventListener('sessionStarted', sessionStartListener);
});
firstSection.root.insertAdjacentElement('beforebegin', unwrapWidget(messageBox));
window.deputy.comms.addEventListener('sessionStarted', sessionStartListener, { once: true });
})
Line 7,298 ⟶ 7,370:
const casePage = _casePage !== null && _casePage !== void 0 ? _casePage : yield DeputyCasePage.build();
return mw.loader.using(['oojs-ui-core', 'oojs-ui.styles.icons-content'], () => {
const firstHeading = casePage.
if (firstHeading) {
const messageBox = DeputyMessageWidget({
Line 7,309 ⟶ 7,381:
closable: true
});
window.deputy.comms.addEventListener('sessionClosed', () => __awaiter(this, void 0, void 0, function* () {
removeElement(unwrapWidget(messageBox));
Line 7,330 ⟶ 7,402:
for (const lastActiveSection of casePage.lastActiveSections) {
for (const heading of csHeadings) {
if (
return heading;
}
Line 7,345 ⟶ 7,417:
static startSession(section, _casePage) {
return __awaiter(this, void 0, void 0, function* () {
const sectionIds = (Array.isArray(section) ? section : [section]).map((_section) =>
// Save session to storage
const casePage = _casePage !== null && _casePage !== void 0 ? _casePage : yield DeputyCasePage.build();
Line 7,445 ⟶ 7,517:
const activeSectionPromises = [];
for (const heading of this.casePage.findContributionSurveyHeadings()) {
const headingId =
if (this.session.caseSections.indexOf(headingId) !== -1) {
activeSectionPromises.push(this.activateSection(this.casePage, heading)
Line 7,504 ⟶ 7,576:
addSectionOverlay(casePage, heading) {
var _a, _b, _c;
const normalizedHeading =
const section = casePage.getContributionSurveySection(normalizedHeading);
const list = section.find((v) => v instanceof HTMLElement && v.tagName === 'UL');
Line 7,562 ⟶ 7,634:
return false;
}
const sectionId =
this.sections.push(el);
const lastActiveSession = this.session.caseSections.indexOf(sectionId);
Line 7,570 ⟶ 7,642:
}
yield casePage.addActiveSection(sectionId);
yield el.loadData();
mw.hook('deputy.load.cci.session').fire();
Line 7,595 ⟶ 7,662:
e0.casePage : e0;
const heading = e0 instanceof DeputyContributionSurveySection ?
e0.heading : normalizeWikiHeading(e1);
const sectionId =
const sectionListIndex = this.sections.indexOf(el);
if (el != null && sectionListIndex !== -1) {
Line 7,613 ⟶ 7,680:
yield DeputyRootSession.setSession(this.session);
yield casePage.removeActiveSection(sectionId);
this.addSectionOverlay(casePage, heading.h);
}
}
Line 15,277 ⟶ 15,344:
*/
static getListingHeader(el) {
var _a;
let listingPage = null;
let previousPivot = (
// Target the ol/ul element itself if a list, target the <p> if not a list.
el.parentElement.tagName === 'LI' ? el.parentElement.parentElement : el.parentElement).previousElementSibling;
let heading;
// Search for a level 4 heading backwards.
while (previousPivot != null &&
// Set the ceiling to be immediately above for efficiency.
((_a = (heading = normalizeWikiHeading(previousPivot, previousPivot.parentElement))) === null || _a === void 0 ? void 0 : _a.level) !== 4) {
previousPivot = previousPivot.previousElementSibling;
}
Line 15,287 ⟶ 15,359:
return false;
}
const h4Anchor = heading.h.querySelector('a');
if
listingPage = pagelinkToTitle(h4Anchor);
// Identify if the page is a proper listing page (within the root page's
Line 16,724 ⟶ 16,796:
}
/**
* Adds a panel containing the "new listing" buttons (single and multiple)
* and the panel container (when filing a multiple-page listing) to the proper
* ___location: either at the end of the copyright problems section or replacing
* the redlink to the blank copyright problems page.
*/
addNewListingsPanel() {
document.querySelectorAll('.mw-headline
const href = el.getAttribute('href');
const url = new URL(href, window.___location.href);
if (equalTitle(url.searchParams.get('title'), CopyrightProblemsPage.getCurrentListingPage()) ||
url.pathname === mw.util.getUrl(CopyrightProblemsPage.getCurrentListingPage().getPrefixedText())) {
if (el.classList.contains('external') || el.classList.contains('redlink')) {
//
}
// Check if it
// and if so,
if (currentPivot.children.length > 1) {
return;
}
mw.loader.using([
'oojs-ui-core',
Line 16,764 ⟶ 16,829:
'mediawiki.widgets.TitlesMultiselectWidget'
], () => {
});
}
else {
// This is in a heading. Let's place it after the section heading.
const heading = normalizeWikiHeading(el);
if (heading.root.classList.contains('dp-ia-upgraded')) {
return;
}
heading.root.classList.add('dp-ia-upgraded');
mw.loader.using([
'oojs-ui-core',
Line 16,775 ⟶ 16,845:
'mediawiki.widgets.TitlesMultiselectWidget'
], () => {
});
}
Line 17,185 ⟶ 17,255:
function findSectionHeading(sectionHeadingName, n = 1) {
let currentN = 1;
const headlines = Array.from(document.querySelectorAll(
// Old style headings
[1, 2, 3, 4, 5, 6].map(v => `h${v} > .mw-headline`).join(',') +
',' +
// New style headings
[1, 2, 3, 4, 5, 6].map(v => `mw-heading > h${v}`).join(',')));
for (const el of headlines) {
if (el instanceof HTMLElement && el.innerText === sectionHeadingName) {
Line 17,281 ⟶ 17,356:
getSectionHTML: getSectionHTML,
getSectionId: getSectionId,
guessAuthor: guessAuthor,
isWikiHeading: isWikiHeading,
msgEval: msgEval,
normalizeTitle: normalizeTitle,
normalizeWikiHeading: normalizeWikiHeading,
nsId: nsId,
openWindow: openWindow,
Line 17,293 ⟶ 17,368:
purge: purge,
renderWikitext: renderWikitext,
sectionHeadingN: sectionHeadingN,
toRedirectsObject: toRedirectsObject
};
|