// ==UserScript== // @name Wiki: Cytuj OpenLibrary // @namespace pl.enux.wiki // @version 1.2.0 // @description Polskie cytowanie książek na podstawie OpenLibrary. // @author Nux // @match https://openlibrary.org/books/* // @grant none // @updateURL https://github.com/Eccenux/wiki-CytujOpenLibrary/raw/master/CytujOpenLibrary.meta.js // @downloadURL https://github.com/Eccenux/wiki-CytujOpenLibrary/raw/master/CytujOpenLibrary.user.js // ==/UserScript== /** * Fetch & render. */ var CytujOpenLibrary = class { /** Fetch (main). */ async load() { this.rdf = await cytuj.loadCurrentRdf(); this.json = await cytuj.loadCurrentJson(); let quote = { authors: this.readAuthors(), title: this.json.title, isbn: this.readIsbn(), publishers: this.json.publishers, publish_places: this.json.publish_places, date: this.json.publish_date, lang: this.readLangs(), ol: this.json.key.replace('/books/OL', ''), lccn: this.firstArray(this.json.lccn), }; return quote; } /** Render data for pl.wiki */ renderPl(quote) { let author = this.flatArray(quote.authors, ', '); let publisher = this.firstArray(quote.publishers); let lang = this.firstArray(quote.lang); return `{{Cytuj książkę | autor = ${author} | tytuł = ${quote.title} | wydawca = ${publisher} | data = ${quote.date} | isbn = ${quote.isbn} | język = ${lang} | strony = }}`.replace(/\n\s+/g, ' '); } renderPlGeneric(quote) { let author = this.flatArray(quote.authors, '; '); let publisher = this.firstArray(quote.publishers); let publish_place = this.firstArray(quote.publish_places); let lang = this.firstArray(quote.lang); return `{{Cytuj | autor = ${author} | tytuł = ${quote.title} | wydawca = ${publisher} | miejsce = ${publish_place} | data = ${quote.date} | isbn = ${quote.isbn} | lccn = ${quote.lccn} | ol = ${quote.ol} | język = ${lang} | s = }}` .replace(/\n\s+/g, ' ') .replace(/\| (wydawca|miejsce|lccn|ol) = +(?=\|)/g, ' ') ; } /** Render data for en.wiki. */ renderEn(quote) { let author = this.flatArray(quote.authors, ', '); let publisher = this.firstArray(quote.publishers); let lang = this.firstArray(quote.lang); return `{{cite book |author=${author} |title=${quote.title} |publisher=${publisher} |date=${quote.date} |isbn=${quote.isbn} |lang=${lang} |ol=${quote.ol} |page= }}`.replace(/\n\s+/g, ' '); } /** @private Load RDF XML as a promise. */ loadCurrentRdf() { let url = document.querySelector('#historyTools a[href$=rdf]').href; return fetch(url) .then(response => response.text()) .then(str => ((new DOMParser()).parseFromString(str, 'text/xml'))) } /** @private Load JSON based object as a promise. */ loadCurrentJson() { let url = document.querySelector('#historyTools a[href$=json]').href; return fetch(url) .then(response => response.json()) } /** @private Read authors as an array. */ readAuthors() { const authorList = this.rdf.getElementsByTagName("bibo:authorList")[0]; if (authorList) { const authorNames = authorList.getElementsByTagName("foaf:name"); return [...authorNames].map(el=>el.textContent); } return []; } /** @private Read ISBN 13 with 10 fallback. */ readIsbn() { let isbn = ''; if (Array.isArray(this.json.isbn_13)) { isbn = this.firstArray(this.json.isbn_13); } else if (Array.isArray(this.json.isbn_10)) { isbn = this.firstArray(this.json.isbn_10); } else if (Array.isArray(this.json.isbn)) { isbn = this.firstArray(this.json.isbn); } return isbn; } /** @private Read langs as an array. */ readLangs() { const langMap = { "ara": "ar", "bul": "bg", "chi": "zh", "hrv": "hr", "ces": "cs", "dan": "da", "nld": "nl", "eng": "en", "est": "et", "fin": "fi", "fra": "fr", "deu": "de", "ell": "el", "hin": "hi", "hun": "hu", "ita": "it", "jpn": "ja", "lav": "lv", "lit": "lt", "nor": "no", "pol": "pl", "por": "pt", "ron": "ro", "rus": "ru", "srp": "sr", "slk": "sk", "slv": "sl", "spa": "es", "swe": "sv", "ukr": "uk" }; if (Array.isArray(this.json.languages) && this.json.languages.length) { return this.json.languages.map(l=>l.key.replace('/languages/', '')).map(k=>{ if (k in langMap) { return langMap[k]; } console.warn('[CytujOpenLibrary]', 'Unknown language:', k); return k; }); } return []; } /** @private Safely flatten the array. */ flatArray(arr, separator) { if (!Array.isArray(arr) || !arr.length) { return ''; } return arr.join(separator); } /** @private Safe 1st. */ firstArray(arr) { if (!Array.isArray(arr) || !arr.length) { return ''; } return arr[0]; } } /** * Quote actions (buttons). */ var QuoteActions = class { /** * cons. * @param {CytujOpenLibrary} cytuj */ constructor(cytuj) { this.q = cytuj; /** cache */ this.quote = null; } /** * Get Polish. * @param {Function} callback */ getText(lang, callback) { let render = (quote)=>this.q.renderPl(quote); switch (lang) { case 'pl-generic': render = (quote)=>this.q.renderPlGeneric(quote); break; case 'en': render = (quote)=>this.q.renderEn(quote); break; } // don't load 2nd time (assumes the descriptions don't change dynamically) if (this.quote && typeof this.quote === 'object') { callback(render(this.quote)); return; } this.q.load().then((quote)=>{ //console.log('[QuoteActions]', 'data:', quote); this.quote = quote; callback(render(quote)); }); } /** Add styles. */ addStyles() { if (this._stylesDone) { return; } this._stylesDone = true; document.body.insertAdjacentHTML('afterbegin', ``) } /** Open with quote text. */ openDialog(text, tplLang) { let id = 'nux-quote-dialog'; // delete previous let previous = document.getElementById(id); if (previous) { previous.remove(); } else { this.addStyles(); } let dialog = document.createElement('dialog'); dialog.id = id; dialog.className = 'wikiquote'; dialog.style.cssText = `width: 30em;`; let wikiLang = tplLang.replace(/-.+/, ''); // pl-generic = pl; en-us = en let pagesParam = tplLang==='pl' ? 'strony' : (tplLang==='pl-generic' ? 's' : 'page'); dialog.innerHTML = `