「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 { | |||
const token = await fetch(mw.config.get('wgArticlePath').replace('$1', "特別:トークページ")).then(r => r.text()); | |||
const doc = new DOMParser().parseFromString(token, 'text/html'); | |||
const title = doc.querySelector('.mw-page-title-main'); | |||
if (title) mw.forum.username = title.innerText; | |||
} 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'); | ||
fetch('/mediawiki/forum-proxy.php', { | |||
method: 'POST', | |||
title: mw.config.get('wgPageName'), | headers: { 'Content-Type': 'application/json' }, | ||
body: JSON.stringify({ | |||
title: mw.config.get('wgPageName'), | |||
appendtext: `\n{{post|...}}`, // feditの場合は text: を使う | |||
}). | summary: summary | ||
location.reload(); | }) | ||
}). | }).then(r => r.json()).then(data => { | ||
mw.notify(msg. | 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 | const preview = document.querySelector('#f-trip-preview'); | ||
const saveBtn | 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 | 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 | 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 | 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(); | ||