MediaWiki:Check tags.js
Вы находитесь на сайте "Архив статей из ЭЕЭ и статей на еврейские темы из Википедии"
Замечание: Чтобы после сохранения увидеть сделанные изменения, очистите кеш своего браузера: Mozilla / Firefox: Ctrl+Shift+R, IE: Ctrl+F5, Safari: Cmd+Shift+R, Konqueror: F5, Opera: через меню Tools→Preferences.
//Скрипт проверяет правильность закрытия тегов. //Автор: X-romix if (wgAction == 'edit' || wgAction == 'submit') addOnloadHook(function(){ var wpSave = document.getElementById('wpSave'); if (!wpSave) return; addHandler(wpSave, 'click', XRomix_CheckTagsHandler); }); function XRomix_CheckTagsHandler(e){ var xSelectionStart=0; var xSelectionEnd=0; var wpTextbox1 = document.editform.wpTextbox1; var isCancel=false; var text=document.editform.wpTextbox1.value; var isCancel=!XRomix_CheckTags(text); if(isCancel){ setSelectionRange(wpTextbox1, xSelectionStart, xSelectionEnd); isCancel= !window.confirm("Имеются ошибки форматирования. Всё равно сохранить?"); }else{ setRedWindow(""); //Очищаем красное окно, если оно было } if (isCancel){ //отменить нажатие кнопки e = e || window.event //из-за различий в IE и стандартных браузерах if (e.preventDefault) e.preventDefault(); else e.returnValue = false //остановить действие, снова по-разному return false //на всякий случай } //Выводит красное окно предупреждения function setRedWindow(res){ var w = document.getElementById('XRomix_editpage_CheckTags'); if (res!=""){ var wpSummary = document.getElementById('wpSummary') if (!wpSummary) return var w = document.getElementById('XRomix_editpage_CheckTags'); if(!w){ w = document.createElement('span') w.id = 'XRomix_editpage_CheckTags' wpSummary.parentNode.insertBefore(w, wpSummary.nextSibling); } w.innerHTML = '<div style="padding:10px; margin:5px; background:#FF8080; border:1px solid red;">'+ 'Имеются незакрытые (или неправильно закрытые) элементы HTML или вики-разметки. ' + res +' '+ ' (<a href="' + wgArticlePath.replace(/\$1/, 'Википедия:Как править статьи') + '" title="(ссылка откроется в новом окне)" target=_blank>подробнее ↗</a>)</div>'; }else{ if(w) w.innerHTML=''; //Если нет ошибки, то очищаем } } ////////////////////////////////////// //генерирует строку из пробелов указанной длины function generateSpaces(len){ var s1=" "; while(s1.length<len){ s1+=s1; } return s1.substr(0,len); } ////////////////////////////////////// //Проверяет теги function XRomix_CheckTags(text){ ////////////////////////////////////// //Заменяет текст между открывающим и закрывающим тегами на пробелы function replaceTags(tag1, tag2){ while(1==1){ var p=txt.search(tag1); if(p==-1) break; var p1=txt.indexOf(tag2,p); if(p1==-1) { //ошибка, закрывающий тег не найден setRedWindow('Не закрыт элемент '+htmlEncode(tag1)+'.'); xSelectionStart=p; xSelectionEnd=p+tag2.length+1; return false; } var w1=generateSpaces(p1-p+tag2.length); var left=txt.substr(0, p); var right=txt.substr(p1+tag2.length); txt=left+w1+right; } return true; } ////////////////////////////////////// //Заменяет тег на пробелы function replace1Tag(tag1){ var p=txt.indexOf(tag1); if(p==-1) return; var w1=generateSpaces(tag1.length); var left=txt.substr(0, p); var right=txt.substr(p+tag1.length); txt=left+w1+right; } var ok=0; if (document.URL.match(/\.js&action=(edit|submit)/)){ return true; //JavaScript не проверяем }else if (document.URL.match(/\.css&action=(edit|submit)/)){ return true; //CSS не проверяем }else if (wgTitle.match (/(Шаблон|Template)\:/)){ return true; //Шаблоны не проверяем }else if ('code'.replace(/d/g, 'r') != 'core'){ //Проверяем, поддерживает ли браузер регулярные выражения (RegExp) return true; } var wpTextbox1 = document.editform.wpTextbox1; if(!wpTextbox1) return true; var txt = wpTextbox1.value; var ok=replaceTags(/<nowiki>/, "</nowiki>"); if(!ok) return false; var ok=replaceTags(/<\!\-\-/, "-->"); if(!ok) return false; var ok=replaceTags(/<math>/, "</math>"); if(!ok) return false; var ok=replaceTags(/<source[\s>]/, "</source>"); if(!ok) return false; var ok=replaceTags(/<pre[\s>]/, "</pre>"); if(!ok) return false; var arrPos = new Array(); var arrTags= new Array(); var arr = txt.match(/(<[\/]?[A-Za-z][^>]*>|\[\[|\]\]|\{\{|\}\})/g); if(arr==null) return true; //Нет тегов для проверки - возврат if(arr){ for(var i=0; i<arr.length; i++){ var w=arr[i]; var pos=txt.indexOf(w); //Запоминаем позицию и текст тега arrPos.push(pos); arrTags.push(w); //Заменяем тег на пробелы replace1Tag(w); } } var arrStackTags = new Array(); var arrStackPos = new Array(); for(var i=0; i<arrTags.length; i++){ var TagName=arrTags[i]; var TagPos=arrPos[i]; if (TagName.search(/(\/[\s]*>|<hr>|<br>)/) >=0 ){ // <тег/> continue; //пропускаем такие теги, поскольку они не требуют закрытия }else if(TagName.search(/<[a-zA-Z][^>]*>/) >=0){ //открывающий <тег ...> //помещаем тег и его позицию в стек arrStackTags.push(TagName); arrStackPos.push(TagPos); }else if(TagName.search(/<\/[^>]+>/) >=0){ //Закрывающий </тег> var TagNameN=TagName.replace(/[<>\/]/g, ""); TagNameN=TagNameN.toLowerCase(); //Нормализованное имя тега - без угловых скобок и / if (arrStackTags.length==0){ setRedWindow('Неожиданный закрывающий тег '+htmlEncode(TagName)+'.') xSelectionStart=TagPos; xSelectionEnd=TagPos+TagName.length; return false; }else{ var TagName2=arrStackTags.pop(); var TagPos2=arrStackPos.pop(); var TagName2N=TagName2.replace(/[\s][^>]*/, ""); //убираем все после первого пробела TagName2N=TagName2N.replace(/[<>\/]/g, "");//убираем </> TagName2N=TagName2N.toLowerCase(); if(TagNameN!=TagName2N){ setRedWindow('Неожиданный закрывающий тег '+htmlEncode(TagName)+' после открывающего тега '+htmlEncode(TagName2)+'.'); xSelectionStart=TagPos; xSelectionEnd=TagPos+TagName.length; return false; } } }else if(TagName=="[["){ arrStackTags.push(TagName); arrStackPos.push(TagPos); }else if(TagName=="{{"){ arrStackTags.push(TagName); arrStackPos.push(TagPos); }else if(TagName=="]]"){ if (arrStackTags.length==0){ setRedWindow('Неожиданный закрывающий элемент '+htmlEncode(TagName)+'.'); xSelectionStart=TagPos; xSelectionEnd=TagPos+TagName.length; return false; }else{ var TagName2=arrStackTags.pop(); var TagPos2=arrStackPos.pop(); if(TagName2!="[["){ setRedWindow('Неожиданный закрывающий тег '+htmlEncode(TagName)+' после открывающего тега '+htmlEncode(TagName2)+'.'); xSelectionStart=TagPos; xSelectionEnd=TagPos+TagName.length; return false; } } }else if(TagName=="}}"){ if (arrStackTags.length==0){ setRedWindow('Неожиданный закрывающий элемент '+htmlEncode(TagName)+'.'); xSelectionStart=TagPos; xSelectionEnd=TagPos+TagName.length; return false; }else{ var TagName2=arrStackTags.pop(); var TagPos2=arrStackPos.pop(); if(TagName2!="{{"){ setRedWindow('Неожиданный закрывающий тег '+htmlEncode(TagName)+' после открывающего тега '+htmlEncode(TagName2)+'.'); xSelectionStart=TagPos; xSelectionEnd=TagPos+TagName.length; return false; } } } }//for if(arrStackTags.length>0){ var TagName=arrStackTags.pop() var TagPos=arrStackPos.pop(); setRedWindow('Имеется незакрытый элемент '+htmlEncode(TagName)+'.'); xSelectionStart=TagPos; xSelectionEnd=TagPos+TagName.length; return false; }//if return true; //нет ошибок }//function //подсчитывает концы строк в фрагменте текста function countCrlf(str){ str=""+str; var arr=str.match(/\n/g); //Теперь массив содержит концы строк - возвращаем его длину if (arr) return arr.length; return 0; } //Извлекает первую строку (до \n или \r) из строки function get1string(text){ var p=text.indexOf("\n"); var p1=text.indexOf("\r"); if(p1!=-1 && p!=-1){ if(p>p1) p=p1; } if(p!=-1){ text=text.substr(0, p); } return text; } //Браузеро-независимый setSelectionRange - изменяет начало и конец //выделенного фрагмента в поле ввода input function setSelectionRange(input, start, end){ if(!input) return; if(!input.value) return; var text=input.value.substring(start, end); text=get1string(text); if (input.setSelectionRange) {//Mozilla/Opera //Попытаемся спозиционировать курсор на нужный текст if (self.find) {//Mozilla, в Опере не работает input.focus(); input.setSelectionRange(start, start); var caseSensitive = false var backwards = false var wrapAround = false self.find(text, caseSensitive, backwards, wrapAround); } //Выделим диапазон input.focus(); input.setSelectionRange(start, end); }else if (document.selection && document.selection.createRange) { //Internet Explorer //IE проглючивает с началом и концом выделенного фрагмента - вносим исправление var cnt1=countCrlf(input.value.substring(0, start)); var cnt2=countCrlf(input.value.substring(start, end)); var range = input.createTextRange(); if(range.findText){ input.focus(); range.collapse(true); range.moveStart("character", start - cnt1); range.moveEnd("character", start - cnt1); range.select(); range.findText(text); range.collapse(true); } var range = input.createTextRange(); //Выделяем диапазон в IE input.focus(); range.collapse(true); range.moveStart("character", start - cnt1); range.moveEnd("character", end - start - cnt2); range.select(); } } //Кодирование спецсимволов HTML function htmlEncode(s){ s=s.replace(/[\&]/g, "&"); s=s.replace(/[<]/g, "<"); s=s.replace(/[>]/g, ">"); return s; } }