Користувач:Sergento/addQuote.js

Матеріал з Вікіцитат

Увага: Після публікування слід очистити кеш браузера, щоб побачити зміни.

  • Firefox / Safari: тримайте Shift, коли натискаєте Оновити, або натисніть Ctrl-F5 чи Ctrl-Shift-R (⌘-R на Apple Mac)
  • Google Chrome: натисніть Ctrl-Shift-R (⌘-Shift-R на Apple Mac)
  • Internet Explorer / Edge: тримайте Ctrl, коли натискаєте Оновити, або натисніть Ctrl-F5
  • Opera: натисніть Ctrl-F5
if( window.AddQuoteToPage === undefined ) {
	window.AddQuoteToPage = {
		
		fields: {},
		
		pageid: 0,
		pagetitle: '',
		pagecontent: '',
		pagesections: {},
		pagesources: [],
		sourcesectionpos: -1,
	
		install: function () {
				var aqp = this;
				aqp.Caption = 'Додати цитату'; 
				
				var pLink = mw.util.addPortletLink( 'p-views', '#', aqp.Caption, 'ca-addquote', 'Add quote', '', '#ca-history' );
				$( pLink ).click( function ( e ) {
					e.preventDefault();
					
					aqp.requestQuote();
				});
			},
		
		requestQuote: function () {
			var aqp = this;
			if( $( '#aqp-dialog' ).length === 0 ) {
				aqp.createDialog();
			}
			mw.loader.using( 'jquery.ui', function () {
				$( '#aqp-dialog' ).dialog({
					width: 400,
					buttons: {
						'Зберегти': function () {
							aqp.saveQuote();
						}
					}
				});	
			});
		},
		
		saveQuote: function() {
			var qText = $( '#aqp-quote' ).val();
			var qOrig = $( '#aqp-original' ).val();
			var qComm = $( '#aqp-comment' ).val();
			var qAuth = $( '#aqp-author' ).val();
			var qSrce = $( '#aqp-source' ).val().trim();
			
			var newContent = this.pagecontent;
			
			var needRefs = false;
			if (qSrce !== '')
			{
				if (this.pagesources.indexOf(qSrce) > -1)//якщо існуюче джерело
				{
					// якщо воно уже примітка
					if (qSrce.search(/<ref[^>]*(\/>|>[^<]*<\/ref>)/) === 0)
					{
						var nameMatch = /<ref[^>]*name[ ]*=[ ]*"([^"]*)"[^>]*>/.exec(qSrce);
						if (nameMatch !== null) // якщо примітка вже має назву - додаємо її за назвою
						{
							qSrce = '<ref name="'+ nameMatch[1] +'"/>';
						}
						// а якщо не має...
						else
						{
							// визначаємо назву
							var refName = this.getSourceCaption(qSrce);
							if (refName === qSrce || refName.search('"') > -1) // якщо коротку назву не вдається визначити, або якщо вона містить лапки, треба звагранити шось унікальне
							{
								 refName = new Date().getTime(); // напр. так...
							}
							
							// тепер треба підставити у тексті цю примітку уже із назвою.
							newContent = newContent.replace(qSrce, qSrce.replace('<ref', '<ref name="' + refName + '"'));
							// а до нової цитати додається тільки як назва
							qSrce = '<ref name="' + refName + '"/>';
						}
					}
					else
					// інакше додаємо його ще і як примітку
					{
						qSrce = '<ref>' + this.getSourceCaption() + '</ref>';
						needRefs = true; // переконатися, що є розділ з примітками
					}
				}
				else
				{
					// якщо нове джерело, треба переконатися, що є розділ для приміток і оформити саме джерело як примітку, якщо треба
					needRefs = true;
					if (qSrce.search('<ref') !== 0)
						qSrce = '<ref>' + qSrce + '</ref>';
				}
			}
			var newQuote = '{{Q\n|Цитата = ' + qText;
			
			newQuote = newQuote + qSrce;
			
			newQuote = newQuote + '\n|Оригінал = ' + qOrig + '\n|Коментар = ' + qComm + '\n|Автор = ';
			var aDif = false;
			if (qAuth !== '' && qAuth.trim() != this.pagetitle)
			{
				newQuote = newQuote + qAuth;
				aDif = true;
			}
			newQuote = newQuote + '\n}}\n\n';
			
			// якщо є розділи - треба помістити новий контент у потрібне місце
			if (this.pagesections.length > 0)
			{
				var qFrom = -1;
				var hRegex = RegExp('==( )*цитат[^=]*==', 'gi');
				for (var i = 0; i<this.pagesections.length; i++)
				{
					if (hRegex.test(this.pagesections[i]))
					{
						qFrom = i;
						break;
					}
				}
				var qAbout = -1;
				hRegex = RegExp('==( )*про[^=]*==', 'gi');
				for (i = 0; i<this.pagesections.length; i++)
				{
					if (hRegex.test(this.pagesections[i]))
					{
						qAbout = i;
						break;
					}
				}
				var isPerson = /{{особа/gi.test(this.pagecontent);
				
				var place = -1;
				var header = 'Цитати';
				if (!aDif)
				{
					place = qFrom;
				}
				else
				{
					if (isPerson)
					{
						place = qAbout;
						header = 'Про';
					}
					else
						if (qAbout > 0)
						{
							place = qAbout;
							header = 'Про';
						}
						else
							place = qFrom;
				}
				if (place < 0)
					newQuote = '== ' + header + ' ==\n' + newQuote;
					
				newContent = this.addToSection(newQuote, place, newContent);

				// якщо потрібно додати розділ приміток
				if (needRefs)
				{
					// якщо його ще нема
					if (this.pagecontent.indexOf('{{reflist') < 0 && this.pagecontent.indexOf('<references') < 0)
					{
						// він має бути наступним за всіма (першими двома?) цитатами
						place = Math.max(qFrom, qAbout);
						
						newContent = this.addToSection('== Примітки ==\n{{reflist}}\n', place, newContent);
					}
				}
			}
			else
			{
				// якщо нема розділів - створити потрібні
				if (aDif)
				{
					newContent = this.addToTheEnd('== Про ==\n' + newQuote, newContent);
				}
				else
				{
					newContent = this.addToTheEnd('== Цитати ==\n', newContent);
				}
				
				if (needRefs)
				{
					newContent = this.addToTheEnd('== Примітки ==\n{{reflist}}\n', newContent);
				}
			}
			
			this.writePage(newContent);
		},
		
		addToSection: function(textToAdd, sectionNumber, content){
			// якщо потрібний розділ останній - додаємо в кінець
			if (sectionNumber >= this.pagesections.length)
			{
				return this.addToTheEnd(textToAdd, content);
			}
			else
			{
				// якщо неостанній - додаємо новий вміст в кінець розділу
				where = RegExp('\n(?:\n)*' + this.pagesections[sectionNumber+1]).exec(content);
				
				return this.addToTheEnd(textToAdd, content.slice(0, where.index + 1)) + content.slice(where.index + 1);
			}
		},
		
		addToTheEnd: function(textToAdd, textAddTo){
			var templs = textAddTo.match(RegExp('{{([^}|]*)(?:\\|[^}]*?|)}}', 'gi'));
			var templPos = textAddTo.length;
			var catPos = textAddTo.length;
			var qExists = false; 
			var catMatch = RegExp('\\[\\[Категорія:[^\\]]*?]]').exec(textAddTo);
			if (catMatch !== null)
				catPos = catMatch.index;
			
			// якщо останнім у розділі є не шаблон цитати - шукаємо його позицію
			if (templs.length > 0)
			{
				for (var i = templs.length - 1; i >= 0; i--)
				{
					var templMatch = /{{([^}|]*)(?:\\|[^}]*?|)}}/.exec(templs[i]);
					if (templMatch[1].trim() !== 'Q')
					{
						templPos = RegExp(templs[i]).exec(textAddTo).index;
					}
					else
					{
						qExists = true;
						break;
					}
				}
			}
			
			// якщо є шаблон Q і є категорія, чи шаблон не цитати - додаємо перед ним
			if (qExists && (templPos < textAddTo.length || catPos < textAddTo.length))
			{
				return textAddTo.slice(0, Math.min(templPos, catPos)) + textToAdd + textAddTo.slice(Math.min(templPos, catPos));
			}
			// інакше - просто в кінець
			else
			{
				return textAddTo.trim() + '\n\n' + textToAdd;
			}
		},
		
		writePage: function(newPageContent){
			var apiParams = {
				format: 'json',
				action: 'edit',
				pageid: this.pageid, 
				summary: 'adding quote with QuoteAdder (test)', 
				text: newPageContent,
				token: mw.user.tokens.get('csrfToken')
			};
			$.post(mw.util.wikiScript('api'), apiParams, function() {
				location.reload();
			});
		},
		
		createDialog: function() {
			$( '#mw-content-text' ).append('<div id="aqp-dialog" style="display:none;" title="' + this.Caption + '"></div>');
			var aqp = this;	
			
			mw.util.addCSS( '#aqp-dialog input:not([type="checkbox"]) { width:100%; height: 1.3em; } #aqp-dialog p { margin-bottom: 0; }' );
			mw.util.addCSS( '#aqp-srclinks li { cursor:pointer; font-size:90%; }' );
			var param = {
				action: 'query',
				prop: 'revisions',
				format: 'json',
				rvprop: 'content',
				rvlimit: '1',
				titles: mw.config.get('wgPageName'),
				indexpageids: ''
			};
			
			$.get(mw.util.wikiScript('api'), param).done(function(data) 
				{
					aqp.pageid = data.query.pages[data.query.pageids[0]].pageid;
					aqp.pagetitle = data.query.pages[data.query.pageids[0]].title;
					aqp.pagecontent = data.query.pages[data.query.pageids[0]].revisions[0]['*'];
					
					aqp.addInput('Цитата', 'quote');
					aqp.addInput('Оригінал', 'original');
					aqp.addInput('Коментар', 'comment');
					aqp.addInput('Автор', 'author', aqp.pagetitle, 'text');
					aqp.addInput('Джерело', 'source', undefined, 'text');
					
					// пошук виносок
					var hRE = RegExp('==[^=]*==', 'gi');
					aqp.pagesections = aqp.pagecontent.match(hRE);
					hRE = RegExp('<ref[^/>]*?>(?:.|\n)*?<\\/ref>', 'gi');
					aqp.pagesources = aqp.pagecontent.match(hRE);
					if (aqp.pagesources == null)
					{
						aqp.pagesources = new Array();
					}
					
					// пошук джерел
					var section = '';
					hRE = RegExp('\\* *((?:[^{}\\*]*)?(?:{{(?:[^{}]*)}})?(?:[^{}\\^\\*]*)?)', 'gi');
					var hRegex = RegExp('==( )*джерел[^=]*==', 'gi');
					for (var i = 0; i<aqp.pagesections.length; i++)
					{
						if (hRegex.test(aqp.pagesections[i]))
						{
							aqp.sourcesectionpos = i;
							var section = aqp.pagecontent.slice(aqp.pagecontent.indexOf(aqp.pagesections[i]));
							if (i+1 < aqp.pagesections.length)
							{
								section = section.slice(aqp.pagecontent.indexOf(aqp.pagesections[i+1]))
							}
							while ((m = hRE.exec(section)) != null)
							{
								aqp.pagesources.push(m[1]);
							}
							break;
						}
					}
					
					aqp.addInput('нова книга', '', '{{книга|автор=|заголовок=|посилання=|місто=|видавництво=|рік=|сторінок=|isbn=|ref=}}', 'srclink');
					aqp.addInput('нове посилання', '', '{{Cite web|url=|title=|accessdate=|author=|date=}}', 'srclink');

					for (var i = 0; i < aqp.pagesources.length; i++)
					{
						if (!/<ref[^\/>]*?>( |\n)*<\/ref>/gi.test(aqp.pagesources[i])) // перевірка на порожні теги
							aqp.addInput(aqp.getSourceCaption(aqp.pagesources[i]), '', aqp.pagesources[i], 'srclink');
					}
				});
		},
		
		addSource: function(src){
			var t = src.currentTarget.title;
			
			var qSrce = $( '#aqp-source' );
			qSrce.val(t.replace(/&quot;/g, '"'));
		},
		
		getSourceCaption: function(src){
			var result = src;
			var srcReg = RegExp('{{книга[^}]*\\|заголовок=([^|}]*)[^}]*}}', 'i');
			var srcReg1 = RegExp('{{книга[^}]*\\|рік=([^|}]*)[^}]*}}', 'i');
			while ((match = srcReg.exec(result)) != null)
			{
				var bookHeader = match[1];
				var year = srcReg1.exec(src);
				if (year != null)
				{
					bookHeader = bookHeader + ', ' + year[1];
				}
				result = result.replace(match[0], bookHeader.trim());
			}
			
			srcReg = RegExp('{{(?:C|c)ite(?:_| )web[^}]*\\|title=([^|}]*)[^}]*}}', 'i');
			srcReg1 = RegExp('{{(?:C|c)ite(?:_| )web[^}]*\\|date=([^|}]*)[^}]*}}', 'i');
			while ((match = srcReg.exec(result)) != null)
			{
				var articleHeader = match[1];
				var year = srcReg1.exec(src);
				if (year != null)
				{
					articleHeader = articleHeader + ', ' + year[1];
				}
				result = result.replace(match[0], articleHeader.trim());
			}
			
			srcReg = RegExp('\\[(?:http(?:s|):\\/\\/|(?=www\\.))((?:www\\.|)[^\\/ ]*)[^ ]*([^\\]]*)\\]', 'i');
			while ((match = srcReg.exec(result)) != null)
			{
				result = result.replace(match[0], (match[2] + ' (' + match[1] + ')').trim());
			}
			
			result = result.replace(/<ref[^>]*>/, '');
			result = result.replace(/<\/[ ]*ref[^>]*>/, '');
			
			return result;
		},
		
		isBook: function(src){
			var srcReg = RegExp('{{книга[^}]*\\|заголовок=([^|}]*)[^}]*}}', 'i');
			return srcReg.exec(src) != null;
		},
		
		addInput: function (text, id, value, kind) {
			this.fields[text] = id;
			if (kind === 'srclink')
			{
			 	if ($( '#aqp-srclinks' ).length === 0)
			 	{
			 		$( '#aqp-dialog' ).append('<ul id="aqp-srclinks" >');
			 	}
			}
			else
			{
				$( '#aqp-dialog' ).append('<div>');
			}
			switch (kind)
			{
				case 'text':
					$( '#aqp-dialog div' ).last().append('<p>' + text + ':</p><input id="aqp-' + id + '" value="' + (value || '') + '" />');
					break;
				case 'srclink':
					var aqp = this;
					$( '#aqp-srclinks' ).last().append('<li class="aqp-sourceitem" title="' + value.replace(/"/g, '&quot;') + '" >' + text + '</li>');
					$( '#aqp-srclinks li' ).last().click( function ( e ) {
							e.preventDefault();
							aqp.addSource(e);
						});
					break;
				default:
					$( '#aqp-dialog div' ).last().append('<p>' + text + ':</p><textarea id="aqp-' + id + '" >' + (value || '') + '</textarea>');
					break;
			}
		},
	};
}

$( document ).ready(function () {
	if(mw.config.get( 'wgNamespaceNumber' ) === 0 && !mw.config.get( 'wgIsMainPage' ))
		AddQuoteToPage.install();
});