Difference between revisions of "MediaWiki:Common.js"
Jump to navigation
Jump to search
Line 518: | Line 518: | ||
// Put the first element on the page. | // Put the first element on the page. | ||
var inserted = page.element.querySelector(".pagedjs_page_content").insertAdjacentElement('afterbegin', this.floatPageEls[0]); | var inserted = page.element.querySelector(".pagedjs_page_content").insertAdjacentElement('afterbegin', this.floatPageEls[0]); | ||
− | if (inserted.contains('snap')) { | + | if (inserted.classList.contains('snap')) { |
snapToGrid(inserted); | snapToGrid(inserted); | ||
} | } |
Revision as of 10:57, 3 December 2020
var API_URL = 'https://diversions.constantvzw.org/wiki/api.php'; /** * Make an api url with the given parameters * @param {object} parameters parameters for the url */ function makeApiUrl(parameters) { var params = new URLSearchParams(); for (k in parameters) { params.append(k, parameters[k]); } return API_URL + '?' + params.toString(); } /** * Fetches the given url, parses data as json * @param {string} url url to fetch */ function getJSON (url) { return new Promise(function (resolve, reject) { fetch(url, { method: "GET" }).then(function (response) { if (response.ok) { response.json().then(resolve); //.catch(reject); } else { reject(); } });//.catch(reject); }); } /** * Fetches a list of revisions from the wiki api * Returns a promise * Promise is revolved with a list of revions: * Array<Shape< * comment: string * parentid: integer * revid: integer * timestamp: string * user: string * >> * @param {string} title Title of the lemma */ function getRevisions (title) { return new Promise(function (resolve, reject) { getJSON(makeApiUrl({ action: 'query', prop: 'revisions', rvslots: '*', rvprop: ['timestamp', 'user', 'comment', 'ids'].join('|'), rvlimit: 500, format: 'json', 'titles': title })).then(function (data) { try { var pages = data['query']['pages'], keys = Object.keys(pages), page = pages[keys[0]], revisions = page['revisions']; resolve(revisions); } catch(e) { reject(e); } }); }); } /** * Fetches a parsed revision from the api * Returns a promise * Promise is resolved with a dictionary containing the text * and display title of the lemma. * @param {int} revid Id of the revision */ function getRevision (revid) { return new Promise(function (resolve, reject) { getJSON(makeApiUrl({ action: 'parse', oldid: revid, format: 'json' })).then(function (data) { try { var title = data['parse']['displaytitle'], text = Object.values(data['parse']['text'])[0]; resolve({ title: title, html: text }); } catch (e) { reject(e); } }); }); } function makeTimelineEntry (revision) { var entry = document.createElement('section'); entry.classList.add('timeline--entry'); entry.dataset.revid = revision.revid; var entryData = document.createElement('section'); entryData.classList.add('timeline--entry--data'); var user = document.createElement('span'); user.classList.add('timeline--user'); user.append(document.createTextNode(revision.user)); var timestamp = document.createElement('span'); timestamp.classList.add('timeline--timestamp'); timestamp.append(document.createTextNode(revision.timestamp)); var comment = document.createElement('span'); comment.classList.add('timeline--comment'); comment.append(document.createTextNode(revision.comment)); entryData.append(user, timestamp, comment); entry.append(entryData); entry.addEventListener('click', function () { showRevision(revision.revid); }) return entry; } function makeRevision (revid) { var revision = document.createElement('section'); revision.classList.add('revisions--revision', 'mw-body-content'); revision.dataset.revid = revid; return revision; } // Maybe rename? function makeRevisionStubs (revisions) { var container = document.getElementById('content'); // container.classList.add('revisions'); for (var i = 1; i < revisions.length; i++) { container.append(makeRevision(revisions[i].revid)); } } function makeTimeline (revisions) { var timeline = document.createElement('section'); timeline.classList.add('timeline'); for (var i=0; i < revisions.length; i++) { if (i==0) { revisions[i].revid = 'current'; } timeline.appendChild(makeTimelineEntry(revisions[i])); } return timeline; } function showRevision (revid) { var node = document.querySelector('.revisions--revision[data-revid="'+ revid + '"]'), current = document.querySelector('.timeline--entry[data-revid="'+ revid + '"]'), previous = document.querySelector('.timeline--entry.active'); if (previous) { previous.classList.remove('active'); } current.classList.add('active'); node.scrollIntoView(); if (! node.dataset.loaded) { node.dataset.loading = true; getRevision(revid).then(function (revision) { delete node.dataset.loading; node.dataset.loaded = true; node.innerHTML = revision.html; showRevision(revid); }); } } /** * Transforms the content content div into the container for the revisions. */ function restructurePage () { var contentContainer = document.getElementById('content'), panel = makeRevision('current'); panel.dataset.loaded = true; while(contentContainer.firstChild) { if (contentContainer.firstChild.classList) { contentContainer.firstChild.classList.remove('mw-body'); } panel.appendChild(contentContainer.firstChild); } contentContainer.classList.add('revisions'); contentContainer.appendChild(panel); } function wrap (element, maxWidth, end) { if (maxWidth === null) { maxWidth = 40; } if (end === null) { end = ' \\'; } var lines = element.textContent.split("\n"), wrapped = []; for (var l=0; l < lines.length; l++) { if (lines[l].length > maxWidth) { var line = lines[l]; wrapped.push(line.substring(0, maxWidth).replace(/\s/g, ' ')); line = line.substring(maxWidth); do { wrapped.push((end + line.substring(0, maxWidth - end.length).trim()).replace(/\s/g, ' ')); line = line.substring(maxWidth - end.length); } while (line.length > 0); } else { wrapped.push(lines[l].replace(/\s/g, ' ')) } } var codeElement = document.createElement('code'); codeElement.innerHTML = '<span class="line">' + wrapped.join('</span><span class="line">') + '</span>'; element.replaceWith(codeElement); } function unWikifyReferences () { var links = document.querySelectorAll('a'); for (var i = 0; i < links.length; i++) { var a = links[i]; if (a.href.includes('#cite_note')) { var content = a.textContent; if (content.startsWith('[') && content.endsWith(']')) { a.textContent = content.substring(1, content.length - 1); } } } } (function () { return; var urlParameters = new URLSearchParams(window.location.search), title = urlParameters.get('title'), paged = urlParameters.get('paged'); if (!paged || paged != 'paged') { restructurePage(); if (title) { getRevisions(title).then(function (revisions) { var container = document.getElementById('content'); container.parentElement.appendChild(makeTimeline(revisions)); for (var i = 0; i < revisions.length; i++) { container.append(makeRevision(revisions[i].revid)); } showRevision('current'); }); } } })(); (function() { /** * Heavily of tosser (convert calc expresiion to mm): https://github.com/shyndman/tosser/ */ /** * The MIT License (MIT) * * Copyright (c) 2015 Scott Hyndman * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ 'use strict'; var referenceElement; var units = { 'mm': (72/25.4)*(96/72), // 25.4mm = 72pt 'cm': (72/2.54)*(96/72), 'pt': (96/72), 'in': 96, 'px': 1 }, calcPattern = /calc\s*\(/g, unitReplacementPattern = /(\d+(?:\.\d+)?)(mm|cm|in|pt|px)/gi, varReplacementPattern = /var\((.+?)\)/g; /** * Evaluates a calc expression. * * @param {string} expression A calc expression. * @return {string} The result of the expression, in px units. */ function evaluateCalc (expression) { expression = expression .trim() .replace(/^calc/, '') .replace(unitReplacementPattern, function(m, v, unit) { return parseFloat(v) * units[unit]; }); return eval(expression); }; function evaluateCalcs (input) { if (/calc\s*\(/g.test(input)) { // Test whether there is a calc( in the string var rawChunks = input.split(calcPattern), chunks = [rawChunks.shift()]; // Add anything untill first calc expression for (var i=0; i < rawChunks.length; i++) { var chunk = rawChunks[i], pos = chunk.lastIndexOf(')'), // find last parenthesis in the string. To balance the one removed with // the split. Anything before will be parsed / evaluated to mm's every- // thing after will be added as a tail. body = evaluateCalc(chunk.substr(0, pos)), tail = (pos + 1 < chunk.length) ? chunk.substr(pos+1) : ""; chunks.push(body+tail); } return chunks.join(''); } else { return input; } } function fixUnits (input) { return input.replace(unitReplacementPattern, function(m, v, unit) { return parseFloat(v) * units[unit]; }); } /** * Lookup declaration of given css lookupCssVariable * * https://www.broken-links.com/2014/08/28/css-variables-updating-custom-properties-javascript/ */ function lookupCSSVariable (name) { return window.getComputedStyle(referenceElement).getPropertyValue(name); } function evaluateCSSVariables (input) { while (varReplacementPattern.test(input)) { input = input.replace(varReplacementPattern, function (m, name) { return evaluateCalcs(lookupCSSVariable(name).trim()); }); } return input; } function cssValueToPx (cssValue, element) { referenceElement = (element) ? element : document.body; return parseFloat(fixUnits(evaluateCalcs(evaluateCSSVariables(cssValue.trim())))); } window.cssValueToPx = cssValueToPx; })(); /** - Get revisions - Generate the timeline <section> <section class="timeline--entry" data-revision="{data}" data-time="{time}"> <span class="timeline--user">{ user }</span> <span class="timeline--timestamp">{ timestamp }</span> <span class="timeline--comment">{ comment }</span> </section> </section> - Generate the panels, maybe do not render them all - <section data-revision="{revision}"></section> */ (function () { var urlParameters = new URLSearchParams(window.location.search), paged = urlParameters.get('paged'); prevent = urlParameters.get('prevent'); etherstyles = urlParameters.get('etherstyles'); if (paged == 'paged' && prevent !== 'prevent') { /* var pre = document.querySelectorAll('pre'); while (pre.length > 0) { wrap(pre[0], 50, ' '); pre = document.querySelectorAll('pre'); } */ unWikifyReferences(); /* mw.loader.load('https://unpkg.com/pagedjs@0.1.40/dist/paged.polyfill.js'); */ /* mw.loader.load('https://unpkg.com/pagedjs@0.1.33/dist/paged.polyfill.js'); */ /* mw.loader.load('https://unpkg.com/pagedjs@0.1.28/dist/paged.polyfill.js'); */ const pagedPreviewCSS = ":root{--color-background:whitesmoke;--color-pageBox:#666;--color-paper:white;--color-marginBox:transparent}@media screen{body{background-color:var(--color-background)}.pagedjs_pages{display:flex;width:calc(var(--pagedjs-width) * 2);flex:0;flex-wrap:wrap;margin:0 auto}.pagedjs_page{background-color:var(--color-paper);box-shadow:0 0 0 1px var(--color-pageBox);margin:0;flex-shrink:0;flex-grow:0;margin-top:10mm}.pagedjs_first_page{margin-left:var(--pagedjs-width)}.pagedjs_page:last-of-type{margin-bottom:10mm}.pagedjs_margin-bottom,.pagedjs_margin-bottom-center,.pagedjs_margin-bottom-left,.pagedjs_margin-bottom-left-corner-holder,.pagedjs_margin-bottom-right,.pagedjs_margin-bottom-right-corner-holder,.pagedjs_margin-left,.pagedjs_margin-left-bottom,.pagedjs_margin-left-middle,.pagedjs_margin-left-top,.pagedjs_margin-right,.pagedjs_margin-right-bottom,.pagedjs_margin-right-middle,.pagedjs_margin-right-top,.pagedjs_margin-top,.pagedjs_margin-top-center,.pagedjs_margin-top-left,.pagedjs_margin-top-left-corner-holder,.pagedjs_margin-top-right,.pagedjs_margin-top-right-corner-holder{box-shadow:0 0 0 1px inset var(--color-marginBox)}}"; previewStyles = document.createElement('style'); previewStyles.textContent = pagedPreviewCSS; document.head.appendChild(previewStyles); if (etherstyles == 'etherstyles') { window.setTimeout(function () { window.PagedConfig={auto:false}; jQuery.getScript('https://unpkg.com/pagedjs/dist/paged.polyfill.js').then(function () { function snapToGrid (node) { var lineHeight = cssValueToPx('var(--line-height)', node), height = node.getBoundingClientRect().height, newDesiredHeight = Math.ceil(height/lineHeight) * lineHeight, style = window.getComputedStyle(node), borderTop = cssValueToPx(style.borderTopWidth, node), borderBottom = cssValueToPx(style.borderBottomWidth, node), paddingTop = cssValueToPx(style.paddingTop, node), paddingBottom = cssValueToPx(style.paddingBottom, node); node.style.height = (newDesiredHeight - (borderTop + borderBottom + paddingTop + paddingBottom)) + 'px' } var classElemFloat = 'elem-float-top'; //////////////////////////////////////////////////////////////// function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } } function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } var elemFloatTop = /*#__PURE__*/function (_Paged$Handler) { _inherits(elemFloatTop, _Paged$Handler); var _super = _createSuper(elemFloatTop); function elemFloatTop(chunker, polisher, caller) { var _this; _classCallCheck(this, elemFloatTop); _this = _super.call(this, chunker, polisher, caller); _this.floatPageEls = []; _this.token; return _this; } _createClass(elemFloatTop, [{ key: "layoutNode", value: function layoutNode(node) { // If you find a float page element, move it in the array, if (node.nodeType == 1 && node.classList.contains(classElemFloat) && node.style.display != "none") { var clone = node.cloneNode(true); this.floatPageEls.push(clone); // Remove the element from the flow by hiding it. node.style.display = "none"; } } }, { key: "beforePageLayout", value: function beforePageLayout(page, content, breakToken) { // If there is an element in the floatPageEls array, if (this.floatPageEls.length >= 1) { // Put the first element on the page. var inserted = page.element.querySelector(".pagedjs_page_content").insertAdjacentElement('afterbegin', this.floatPageEls[0]); if (inserted.classList.contains('snap')) { snapToGrid(inserted); } this.floatPageEls.shift(); } } }]); return elemFloatTop; }(Paged.Handler); /////////////////////////////////////////////////////////////// Paged.registerHandlers(elemFloatTop); var links = document.querySelectorAll('a'); for (var i=0;i<links.length;i++){ try { var url = new URL(links[i].href); if (links[i].parentNode.parentNode.classList.contains('nav')) { continue; } if (url.hash && url.hash != '#' && !url.hash.startsWith('#cite')) { links[i].href = url.hash; links[i].dataset.wordLink = true; } } catch (e) { console.log(e); console.log(links[i]); } } window.PagedPolyfill.preview(); }); }, 4000); } else { mw.loader.load('https://unpkg.com/pagedjs/dist/paged.polyfill.js'); } } })(); function loadEtherStyle(url, interval) { function load(url) { fetch(url) .then(function(r) { return r.text()}) .then(function (styles) { var el = document.createElement('style'); el.appendChild(document.createTextNode(styles)); el.setAttribute('data-type', 'etherstyle'); document.head.appendChild(el); window.requestAnimationFrame(function () { var styles = document.querySelectorAll('[data-type="etherstyle"]'); for (var i=0;i<(styles.length-1);i++) { styles[i].remove(); } }); }); } load(url); var urlParameters = new URLSearchParams(window.location.search), reload = urlParameters.get('reload'); if (reload == 'reload') { window.setInterval(function () { load(url); }, interval); } } (function () { var urlParameters = new URLSearchParams(window.location.search), etherstyles = urlParameters.get('etherstyles'); if (etherstyles == 'etherstyles') { loadEtherStyle('https://pad.constantvzw.org/p/diversions.css/export/txt', 7500); } })();