「MediaWiki:Forum.js」の版間の差分

編集の要約なし
編集の要約なし
1行目: 1行目:
// <nowiki>
// <nowiki>
(()=>{
(() => {
     // 設定の読み込み待機
     // 設定の読み込み待機
     const checkConfig = () => {
     const checkConfig = () => {
         if (!window.mw || !mw.config || !mw.loader) return;
         if (!window.mw || !mw.config || !mw.loader) return;
       
 
         // 設定がない場合のデフォルト値
         // 設定がない場合のデフォルト値
         mw.forum = mw.forum || {};
         mw.forum = mw.forum || {};
10行目: 10行目:
         mw.forum.threads = mw.forum.threads || 20;
         mw.forum.threads = mw.forum.threads || 20;
         mw.forum.sticky = mw.forum.sticky || [];
         mw.forum.sticky = mw.forum.sticky || [];
       
 
         const fedit = mw.util.getParamValue('fedit');
         const fedit = mw.util.getParamValue('fedit');
       
 
         // ページ判定(掲示板ページでなければ終了)
         // ページ判定(掲示板ページでなければ終了)
         if(!new RegExp(`^${mw.forum.toppage}(|/.*)$`).test(mw.config.get('wgPageName')) || mw.config.get('wgAction') != 'view'){
         if (!new RegExp(`^${mw.forum.toppage}(|/.*)$`).test(mw.config.get('wgPageName')) || mw.config.get('wgAction') != 'view') {
             return;
             return;
         }
         }
       
 
         // 編集モード時のユーザーチェック
         // 編集モード時のユーザーチェック
         if(fedit && document.querySelector(`[id="${fedit}-user"]`) && document.querySelector(`[id="${fedit}-user"]`).innerText != mw.config.get('wgUserName')){
         if (fedit && document.querySelector(`[id="${fedit}-user"]`) && document.querySelector(`[id="${fedit}-user"]`).innerText != mw.config.get('wgUserName')) {
             return;
             return;
         }
         }


         // UIモジュールの読み込み
         // UIモジュールの読み込み
         mw.loader.load(['mediawiki.ui.button','mediawiki.ui.input','mediawiki.ui.checkbox']);
         mw.loader.load(['mediawiki.ui.button', 'mediawiki.ui.input', 'mediawiki.ui.checkbox']);


         // ========== 直接編集の非表示(管理者以外) ==========
         // ========== 直接編集の非表示(管理者以外) ==========
31行目: 31行目:
         // ※ JS無効化や直接APIアクセスは防げないため、完全な保護が
         // ※ JS無効化や直接APIアクセスは防げないため、完全な保護が
         //  必要な場合は LocalSettings.php でページを保護してください。
         //  必要な場合は LocalSettings.php でページを保護してください。
         if(!mw.config.get('wgUserGroups').includes('sysop')){
         if (!mw.config.get('wgUserGroups').includes('sysop')) {
             const editBlockStyle = document.createElement('style');
             const editBlockStyle = document.createElement('style');
             editBlockStyle.textContent = [
             editBlockStyle.textContent = [
43行目: 43行目:
         }
         }
         // =====================================================
         // =====================================================
       
 
         mw.loader.using(['mediawiki.util', 'mediawiki.user', 'mediawiki.api'], function() {
         mw.loader.using(['mediawiki.util', 'mediawiki.user', 'mediawiki.api'], function () {
             // 動物リスト
             // 動物リスト
             const animals = [
             const animals = [
                 'アライグマ', 'カピバラ', 'キリン', 'ペンギン', 'パンダ',  
                 'アライグマ', 'カピバラ', 'キリン', 'ペンギン', 'パンダ',
                 'ウサギ', 'リス', 'ハリネズミ', 'コアラ', 'ナマケモノ',
                 'ウサギ', 'リス', 'ハリネズミ', 'コアラ', 'ナマケモノ',
                 'イルカ', 'クジラ', 'サメ', 'タコ', 'イカ',
                 'イルカ', 'クジラ', 'サメ', 'タコ', 'イカ',
91行目: 91行目:
                     const saved = localStorage.getItem('forum_anon_settings');
                     const saved = localStorage.getItem('forum_anon_settings');
                     return saved ? JSON.parse(saved) : null;
                     return saved ? JSON.parse(saved) : null;
                 } catch(e) { return null; }
                 } catch (e) { return null; }
             };
             };


98行目: 98行目:
                 try {
                 try {
                     localStorage.setItem('forum_anon_settings', JSON.stringify({ name, tripKey }));
                     localStorage.setItem('forum_anon_settings', JSON.stringify({ name, tripKey }));
                 } catch(e) {}
                 } catch (e) { }
             };
             };
             // ======================================
             // ======================================


             (async()=>{
             (async () => {
                 if (isAnon) {
                 if (isAnon) {
                     // デフォルトの匿名名(IPハッシュベース)
                     // デフォルトの匿名名(IPハッシュベース)
126行目: 126行目:
                 }
                 }


                 if(!mw.forum.username) {
                 if (!mw.forum.username) {
                    // フォールバック
                    // フォールバック
                    try {
                    try {
                        const token = await fetch(mw.config.get('wgArticlePath').replace('$1',"特別:トークページ")).then(r=>r.text());
                        const token = await fetch(mw.config.get('wgArticlePath').replace('$1', "特別:トークページ")).then(r => r.text());
                        const doc = new DOMParser().parseFromString(token,'text/html');
                        const doc = new DOMParser().parseFromString(token, 'text/html');
                        const title = doc.querySelector('.mw-page-title-main');
                        const title = doc.querySelector('.mw-page-title-main');
                        if(title) mw.forum.username = title.innerText;
                        if (title) mw.forum.username = title.innerText;
                    } catch(e) {}
                    } catch (e) { }
                 }
                 }
               
 
                 // メイン処理の開始
                 // メイン処理の開始
                 startForum();
                 startForum();
181行目: 181行目:
                     deleteerror: 'エラー: 削除できませんでした',
                     deleteerror: 'エラー: 削除できませんでした',
                     gotoform: '<a href="#wpTextbox1"><input type="button" value="投稿フォームへ" class="mw-ui-button" id="f-loadmore"></a>',
                     gotoform: '<a href="#wpTextbox1"><input type="button" value="投稿フォームへ" class="mw-ui-button" id="f-loadmore"></a>',
                     editlink: `<a href="${(()=>{const url=new URL(location.href);url.searchParams.set('fedit','$1');return url;})()}" style="margin-left:7px;">編集</a>`
                     editlink: `<a href="${(() => { const url = new URL(location.href); url.searchParams.set('fedit', '$1'); return url; })()}" style="margin-left:7px;">編集</a>`
                 }, mw.forum.msg);
                 }, mw.forum.msg);


191行目: 191行目:
                             list: "allpages",
                             list: "allpages",
                             formatversion: "2",
                             formatversion: "2",
                             [(cont ? 'apcontinue' : 'apprefix')]: (cont ?? new mw.Title(mw.forum.toppage).title+'/'),
                             [(cont ? 'apcontinue' : 'apprefix')]: (cont ?? new mw.Title(mw.forum.toppage).title + '/'),
                             apnamespace: new mw.Title(mw.forum.toppage).namespace,
                             apnamespace: new mw.Title(mw.forum.toppage).namespace,
                             apfilterredir: "nonredirects",
                             apfilterredir: "nonredirects",
209行目: 209行目:
                         });
                         });
                     },
                     },
                     preview: function(){
                     preview: function () {
                         new mw.Api().get({
                         new mw.Api().get({
                             action: "parse",
                             action: "parse",
226行目: 226行目:
                     },
                     },
                     deletePost: async (postId) => {
                     deletePost: async (postId) => {
                         if(!confirm('本当にこの投稿を削除しますか?')) return;
                         if (!confirm('本当にこの投稿を削除しますか?')) return;
                         const source = await (await fetch(mw.config.get('wgScript') + `?title=${mw.config.get('wgPageName')}&action=raw`)).text();
                         const source = await (await fetch(mw.config.get('wgScript') + `?title=${mw.config.get('wgPageName')}&action=raw`)).text();
                         const newText = source.replace(new RegExp(`(\\{\\{post\\|(.*?)\\|${postId}\\|(.*?)\\|4=)((.|\n)*?)(}})`), '$1[Deleted]$6');
                         const newText = source.replace(new RegExp(`(\\{\\{post\\|(.*?)\\|${postId}\\|(.*?)\\|4=)((.|\n)*?)(}})`), '$1[Deleted]$6');
                         new mw.Api().postWithToken('csrf', {
                         fetch('/mediawiki/forum-proxy.php', {
                             action: 'edit',
                            method: 'POST',
                             title: mw.config.get('wgPageName'),
                             headers: { 'Content-Type': 'application/json' },
                            text: newText,
                             body: JSON.stringify({
                            summary: `${msg.deletesummary} #${postId}`,
                                title: mw.config.get('wgPageName'),
                             format: 'json'
                                appendtext: `\n{{post|...}}`, // feditの場合は text: を使う
                         }).done(() => {
                                summary: summary
                             location.reload();
                             })
                         }).fail(() => {
                         }).then(r => r.json()).then(data => {
                             mw.notify(msg.deleteerror);
                             if (data.result === 'Success') {
                                location.reload();
                            } else {
                                mw.notify(msg.posterror);
                                document.querySelector('#f-post').disabled = false;
                            }
                         }).catch(() => {
                             mw.notify(msg.posterror);
                            document.querySelector('#f-post').disabled = false;
                         });
                         });
                     },
                     },
246行目: 254行目:
                         const nameInput = document.querySelector('#f-anon-name');
                         const nameInput = document.querySelector('#f-anon-name');
                         const tripInput = document.querySelector('#f-anon-trip');
                         const tripInput = document.querySelector('#f-anon-trip');
                         const preview = document.querySelector('#f-trip-preview');
                         const preview = document.querySelector('#f-trip-preview');
                         const saveBtn = document.querySelector('#f-save-name');
                         const saveBtn = document.querySelector('#f-save-name');
                         if (!nameInput || !tripInput) return;
                         if (!nameInput || !tripInput) return;


257行目: 265行目:
                         const updatePreview = async () => {
                         const updatePreview = async () => {
                             const name = nameInput.value.trim() || mw.forum.anonDefaultName;
                             const name = nameInput.value.trim() || mw.forum.anonDefaultName;
                             const key = tripInput.value;
                             const key = tripInput.value;
                             if (key) {
                             if (key) {
                                 const trip = await computeTrip(key);
                                 const trip = await computeTrip(key);
271行目: 279行目:
                         // 保存ボタン
                         // 保存ボタン
                         saveBtn.onclick = async () => {
                         saveBtn.onclick = async () => {
                             const newName   = nameInput.value.trim() || mw.forum.anonDefaultName;
                             const newName = nameInput.value.trim() || mw.forum.anonDefaultName;
                             const newTripKey = tripInput.value;
                             const newTripKey = tripInput.value;
                             saveAnonSettings(newName, newTripKey);
                             saveAnonSettings(newName, newTripKey);
                             mw.forum.anonName   = newName;
                             mw.forum.anonName = newName;
                             mw.forum.anonTripKey = newTripKey;
                             mw.forum.anonTripKey = newTripKey;
                             if (newTripKey) {
                             if (newTripKey) {
289行目: 297行目:


                 const mc = document.querySelector('#mw-content-text>.mw-parser-output');
                 const mc = document.querySelector('#mw-content-text>.mw-parser-output');
                 if(!mc) return;
                 if (!mc) return;


                 if(mw.config.get('wgPageName') == mw.forum.toppage){
                 if (mw.config.get('wgPageName') == mw.forum.toppage) {
                     // トップページ処理
                     // トップページ処理
                     if(mw.util.getParamValue('newthread')=='1'){
                     if (mw.util.getParamValue('newthread') == '1') {
                         mc.innerHTML = msg.createform;
                         mc.innerHTML = msg.createform;
                         document.querySelector("#f-preview").onclick = func.preview;
                         document.querySelector("#f-preview").onclick = func.preview;
                         mw.loader.using('ext.wikiEditor');
                         mw.loader.using('ext.wikiEditor');
                         document.querySelector('#f-create').onclick = function(){
                         document.querySelector('#f-create').onclick = function () {
                             let content = '';
                             let content = '';
                             if(mw.forum.zeroTemplate){
                             if (mw.forum.zeroTemplate) {
                                 content += `{{post|System|0|{{subst:#timel:Y/m/d H:i:s}}|4=${mw.forum.zeroTemplate}}}\n`;
                                 content += `{{post|System|0|{{subst:#timel:Y/m/d H:i:s}}|4=${mw.forum.zeroTemplate}}}\n`;
                             }
                             }
312行目: 320行目:
                                 format: 'json'
                                 format: 'json'
                             }).done(() => {
                             }).done(() => {
                                 location.href = `${mw.config.get('wgArticlePath').replace('$1',mw.forum.toppage)}/${document.querySelector('#f-threadname').value}`;
                                 location.href = `${mw.config.get('wgArticlePath').replace('$1', mw.forum.toppage)}/${document.querySelector('#f-threadname').value}`;
                             }).fail(() => {
                             }).fail(() => {
                                 mw.notify(msg.posterror);
                                 mw.notify(msg.posterror);
322行目: 330行目:
                     func.getthreads().then((res) => {
                     func.getthreads().then((res) => {
                         mc.innerHTML = res[0] + msg.toppage_css;
                         mc.innerHTML = res[0] + msg.toppage_css;
                         if(res[1]){
                         if (res[1]) {
                             document.querySelector('#mw-content-text').innerHTML += msg.load_more;
                             document.querySelector('#mw-content-text').innerHTML += msg.load_more;
                             document.querySelector('#f-loadmore').onclick = function(){
                             document.querySelector('#f-loadmore').onclick = function () {
                                 func.getthreads(res[1]).then((mres) => {
                                 func.getthreads(res[1]).then((mres) => {
                                     document.querySelector('#mw-content-text>.mw-parser-output>table>tbody').innerHTML += mres[0];
                                     document.querySelector('#mw-content-text>.mw-parser-output>table>tbody').innerHTML += mres[0];
                                     if(!mres[1]){
                                     if (!mres[1]) {
                                         document.querySelector('#f-loadmore').remove();
                                         document.querySelector('#f-loadmore').remove();
                                     }
                                     }
335行目: 343行目:
                     });
                     });
                     const indicators = document.querySelector('.mw-indicators');
                     const indicators = document.querySelector('.mw-indicators');
                     if(indicators) {
                     if (indicators) {
                         indicators.innerHTML = msg.create;
                         indicators.innerHTML = msg.create;
                         indicators.querySelector("input").onclick = function(){
                         indicators.querySelector("input").onclick = function () {
                             const url=new URL(window.location.href);
                             const url = new URL(window.location.href);
                             url.searchParams.set('newthread','1');
                             url.searchParams.set('newthread', '1');
                             location.href=url;
                             location.href = url;
                         };
                         };
                     }
                     }
                 }else{
                 } else {
                     // スレッドページ処理
                     // スレッドページ処理
                     mc.innerHTML += msg.postform;
                     mc.innerHTML += msg.postform;
349行目: 357行目:
                     mw.loader.using('ext.wikiEditor');
                     mw.loader.using('ext.wikiEditor');
                     const indicators = document.querySelector('.mw-indicators');
                     const indicators = document.querySelector('.mw-indicators');
                     if(indicators) indicators.innerHTML = msg.gotoform;
                     if (indicators) indicators.innerHTML = msg.gotoform;


                     // 名前設定UIを初期化(匿名ユーザーのみ)
                     // 名前設定UIを初期化(匿名ユーザーのみ)
                     func.initAnonSettings();
                     func.initAnonSettings();
                   
 
                     document.querySelector('#f-post').onclick = (async() => {
                     document.querySelector('#f-post').onclick = (async () => {
                         document.querySelector('#f-post').disabled = true;
                         document.querySelector('#f-post').disabled = true;
                         const source = (await (await fetch(mw.config.get('wgScript') + `?title=${mw.config.get('wgPageName')}&action=raw`)).text());
                         const source = (await (await fetch(mw.config.get('wgScript') + `?title=${mw.config.get('wgPageName')}&action=raw`)).text());
                         const lp = source.split('{{post|').length;
                         const lp = source.split('{{post|').length;
                         let summary;
                         let summary;
                         if(fedit) {
                         if (fedit) {
                             summary = `${msg.editsummary} [[${mw.config.get('wgPageName')}#post-${fedit}|#${fedit}]]`;
                             summary = `${msg.editsummary} [[${mw.config.get('wgPageName')}#post-${fedit}|#${fedit}]]`;
                         } else if(document.querySelector('#f-reply-cb').checked) {
                         } else if (document.querySelector('#f-reply-cb').checked) {
                             const replyToUser = document.querySelector('[id="'+document.querySelector('#f-reply').value+'-user"]').innerText;
                             const replyToUser = document.querySelector('[id="' + document.querySelector('#f-reply').value + '-user"]').innerText;
                             summary = `${msg.postsummary} [[${mw.config.get('wgPageName')}#post-${lp}|#${lp}]] ${msg.replysummary} [[User:${replyToUser}|${replyToUser}]]`;
                             summary = `${msg.postsummary} [[${mw.config.get('wgPageName')}#post-${lp}|#${lp}]] ${msg.replysummary} [[User:${replyToUser}|${replyToUser}]]`;
                         } else {
                         } else {
376行目: 384行目:
                             [fedit ? 'text' : 'appendtext']: fedit
                             [fedit ? 'text' : 'appendtext']: fedit
                                 ? source.replace(new RegExp(`\\{\\{post\\|(.*?)\\|${fedit}\\|(.*?)\\|4=((.|\n)*?)}}`), `{{post|$1|${fedit}|$2|4=${document.querySelector('#wpTextbox1').value}}}`)
                                 ? source.replace(new RegExp(`\\{\\{post\\|(.*?)\\|${fedit}\\|(.*?)\\|4=((.|\n)*?)}}`), `{{post|$1|${fedit}|$2|4=${document.querySelector('#wpTextbox1').value}}}`)
                                 : `\n{{post|${mw.forum.username}|${lp}|{{subst:#timel:Y/m/d H:i:s}}|4=${document.querySelector('#wpTextbox1').value}${document.querySelector('#f-reply-cb').checked ? '|re='+document.querySelector('#f-reply').value : ''}${anonParam}}}`,
                                 : `\n{{post|${mw.forum.username}|${lp}|{{subst:#timel:Y/m/d H:i:s}}|4=${document.querySelector('#wpTextbox1').value}${document.querySelector('#f-reply-cb').checked ? '|re=' + document.querySelector('#f-reply').value : ''}${anonParam}}}`,
                             summary: summary,
                             summary: summary,
                             format: 'json'
                             format: 'json'
                         }).done(() => {
                         }).done(() => {
                             if(fedit){
                             if (fedit) {
                                 location.href = `${mw.util.getUrl()}#post-${fedit}`;
                                 location.href = `${mw.util.getUrl()}#post-${fedit}`;
                             }else{
                             } else {
                                 location.reload();
                                 location.reload();
                             }
                             }
391行目: 399行目:
                     });
                     });


                     if(fedit){
                     if (fedit) {
                         location.hash = '#f-form';
                         location.hash = '#f-form';
                         document.querySelector('#wpTextbox1').focus();
                         document.querySelector('#wpTextbox1').focus();
                         (async()=>{(await (await fetch(mw.config.get('wgScript') + `?title=${mw.config.get('wgPageName')}&action=raw`)).text()).replace(new RegExp(`\\{\\{post\\|(.*?)\\|${fedit}\\|(.*?)\\|4=((.|\n)*?)}}`), (m, u, d, t)=>{document.querySelector('#wpTextbox1').value = t;})})();
                         (async () => { (await (await fetch(mw.config.get('wgScript') + `?title=${mw.config.get('wgPageName')}&action=raw`)).text()).replace(new RegExp(`\\{\\{post\\|(.*?)\\|${fedit}\\|(.*?)\\|4=((.|\n)*?)}}`), (m, u, d, t) => { document.querySelector('#wpTextbox1').value = t; }) })();
                     }
                     }


412行目: 420行目:
                             delLink.style.color = '#d33';
                             delLink.style.color = '#d33';
                             delLink.style.cursor = 'pointer';
                             delLink.style.cursor = 'pointer';
                             delLink.onclick = function() {
                             delLink.onclick = function () {
                                 const numText = header.querySelector('.f-number-text').innerText;
                                 const numText = header.querySelector('.f-number-text').innerText;
                                 const postId = numText.replace('#', '');
                                 const postId = numText.replace('#', '');
425行目: 433行目:
         });
         });
     };
     };
   
 
     if (window.mw && window.mw.loader) {
     if (window.mw && window.mw.loader) {
         checkConfig();
         checkConfig();