User:BrandonXLF/Citoid.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/*** Citoid.js ***/

// Get a valid reference from the citoid
// This is not a userscript
// Provides the function "getCitoidRef"
// Documentation at [[User:BrandonXLF/Citoid]]
// By [[User:BrandonXLF]]

window.getCitoidRef = function(URL) {
	try { URL = decodeURIComponent(URL); } catch (e) {}
	URL = encodeURIComponent(URL);

	var dfd = $.Deferred(),
		cfg = mw.config.get('wgCitoidConfig'),
		vecfg = mw.config.get('wgVisualEditorConfig'),
		rest =  cfg.fullRestbaseUrl || cfg.wbFullRestbaseUrl ? (cfg.fullRestbaseUrl || cfg.wbFullRestbaseUrl) + 'v1/data/citation/mediawiki/'
			: vecfg && vecfg.fullRestbaseUrl ? vecfg.fullRestbaseUrl + 'v1/data/citation/mediawiki/'
			: cfg.citoidServiceUrl ? cfg.citoidServiceUrl + '?format=mediawik&search='
			: cfg ? '/api?format=mediawik&search='
			: 'https://en.wikipedia.org/api/rest_v1/data/citation/mediawiki/';
			
	function arrToStr(arr) {
		for (var i = 0; i < arr.length; i++) {
			arr[i] = arr[i].filter(function(str) {
				return !!str;
			}).join(', ');
		}
		
		return arr.join('; ');
	}
			
	function encodeTemplatePart(str) {
		if (Array.isArray(str)) {
			str = arrToStr(str);
		}
		
		return str.replace(/\|/g, '&#124;').replace(/\[/g, '&#91;').replace(/\]/g, '&#93;').replace(/\=/g, '&#61;');
	}
	
	function doMap(out, data, mapData) {
		for (var name in data) {
			if (name == 'url') {
				data[name] = encodeURI(data[name]);
			}

			if (typeof mapData[name] == 'string') {
				out[mapData[name]] = data[name];
			} else if (Array.isArray(mapData[name])) {
				out = doMap(out, data[name], mapData[name]);
			}
		}
		
		return out;
	}

	dfd.notify('Loading reference data.');

	$.get(rest + URL, {
		action: 'query',
		format : 'json'
	}).then(function(res) {
		var data = res[0];

		dfd.notify('Loaded reference data.');
		dfd.notify('Loading Citoid template map.');

		var mapPromise = window.internalGetCitoidRefMap
			? $.Deferred().resolve(window.internalGetCitoidRefMap)
			: $.get(mw.config.get('wgScript'), {
				title: 'MediaWiki:Citoid-template-type-map.json',
				action: 'raw',
				ctype: 'application/json'
			}).then(function(map) {
				window.internalGetCitoidRefMap = map;
				return map;
			});

		mapPromise.then(function(map) {
			var template = map[data.itemType];

			dfd.notify('Loaded Citoid template map.');
			dfd.notify('Loading template data.');
			
			if (!window.internalGetCitoidRefTemplateData) {
				window.internalGetCitoidRefTemplateData = {};
			}

			var templatePromise = window.internalGetCitoidRefTemplateData[template]
				? $.Deferred().resolve(window.internalGetCitoidRefTemplateData[template])
				: $.get(mw.config.get('wgScriptPath') + '/api.php', {
					action: 'templatedata',
					format: 'json',
					formatversion: 2,
					titles: 'Template:' + template,
					redirects: 1
				}).then(function(tdata) {
					for (var id in tdata.pages) {
						window.internalGetCitoidRefTemplateData[template] = tdata.pages[id];
					}

					return tdata.pages[id];
				});

			templatePromise.then(function(tdata) {
				var str = '{{' + template;
				
				dfd.notify('Loaded template data.');

				if (!tdata) {
					dfd.reject('Unable to locate template data for Template:' + template + '.');
					return;
				}

				if (!tdata.maps || !tdata.maps.citoid) {
					dfd.reject('Unable to load Citoid map from Template:' + template + '. Make sure that it is configured properly.');
					return;
				}

				out = doMap({}, data, tdata.maps.citoid);

				for (var k = 0; k < tdata.paramOrder.length; k++) {
					var param = tdata.paramOrder[k];
					
					if (out[param]) {
						str += '|' + param + '=' + encodeTemplatePart(out[param]);
					}
				}

				str += '}}';

				dfd.resolve(str, data.source);
			}, function() {
				dfd.reject('Unable to the template data from Template:' + template + '. Make sure that it exists and the API is enabled.');
			});
		}, function() {
			dfd.reject('Unable to load MediaWiki:Citoid-template-type-map.json. make sure it exists.');
		});
	}, function() {
		dfd.reject('Unable to get the data for the provided reference from citoid. Make sure it is valid and your internet connection to functioning.');
	});

	return dfd.promise();
};