User:Funa-enpitu/Forum/Forum.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
* MediaWiki用掲示板システムを提供する。
* @author Funa-enpitu
* @source https://www.mediawiki.org/wiki/User:Funa-enpitu/Forum/Forum.js
* @license Creative Commons Attribution-ShareAlike License 4.0
* @latest ver.1.6 | 2024/06/13 (JST)
*/
// <nowiki>
(function(){
if(!new RegExp(`^${mw.forum.toppage}(|/.*)$`).test(mw.config.get('wgPageName')) || mw.config.get('wgAction') != 'view'){
return;
}
mw.loader.load(['mediawiki.ui.button','mediawiki.ui.input','mediawiki.ui.checkbox']);
mw.loader.using('mw.util');
mw.forum.sticky = mw.forum.sticky || [];
mw.forum.threads = mw.forum.threads || '20';
(async()=>{mw.forum.username = mw.config.get('wgUserName') || await(()=>{return fetch(mw.config.get('wgArticlePath').replace('$1',"特別:トークページ")).then((r)=>r.text()).then((d)=>{return new DOMParser().parseFromString(d,'text/html').querySelector('.mw-page-title-main').innerText;});})();})();
const msg = Object.assign({
loading: '<p>読み込み中...</p>',
postform: '<div id="f-form"><h2>投稿</h2><div class="mw-ui-checkbox" style="margin-bottom:.3em;"><input type="checkbox" class="mw-ui-checkbox" id="f-reply-cb"><label for="f-reply-cb" style="user-select:none;">返信する</label></div><input type="number" id="f-reply" class="mw-ui-input" style="widht:50%;margin-bottom:.5em;"><textarea accesskey="," id="wpTextbox1" cols="80" rows="25" class="mw-editfont-monospace"></textarea><input type="button" id="f-post" value="投稿" class="mw-ui-button mw-ui-progressive" style="margin-top:.5em;"><input type="button" id="f-preview" value="プレビュー" class="mw-ui-button" style="margin: .5em 0 0 .5em;"><fieldset hidden><legend>プレビュー</legend><div id="f-preview-content"></div></fieldset><style>.mw-ui-checkbox:has(#f-reply-cb:checked)+input{display:block;}#f-reply{display:none;}</style></div>',
postsummary: 'post',
replysummary: 'reply to',
toppage_css: "<style>.f-sticky>td:first-child>a::before{content:'';background-image:url(https://upload.wikimedia.org/wikipedia/commons/a/a5/OOjs_UI_icon_pushPin.svg);width:.8em;height:.8em;margin-right:.2em;display:inline-block;background-size:.8em}#f-loadmore{display:block;margin-left:auto;margin-right:auto;}</style>",
load_more: '<input type="button" value="もっと読み込む" class="mw-ui-button" id="f-loadmore">',
create: '<input type="button" class="mw-ui-button mw-ui-progressive" value="スレッドを作成">',
createform: '<div id="f-form"><label>スレッド名: <input type="text" id="f-threadname" class="mw-ui-input" style="margin-bottom:.5em;"></label><textarea accesskey="," id="wpTextbox1" cols="80" rows="25" class="mw-editfont-monospace"></textarea><input type="button" value="スレッドを作成" id="f-create" class="mw-ui-button mw-ui-progressive" style="margin-top:.5em;"><input type="button" id="f-preview" value="プレビュー" class="mw-ui-button" style="margin: .5em 0 0 .5em;"><fieldset hidden><legend>プレビュー</legend><div id="f-preview-content"></div></fieldset></div>',
createthreadsummary: 'スレッドの作成',
posterror: 'エラー: 投稿できませんでした',
gotoform: '<a href="#wpTextbox1"><input type="button" value="投稿フォームへ" class="mw-ui-button" id="f-loadmore"></a>'
}, mw.forum.msg);
const func = {
getthreads: async (cont) => {
return await new mw.Api().get({
action: "query",
format: "json",
list: "allpages",
formatversion: "2",
[(cont ? 'apcontinue' : 'apprefix')]: (cont ?? new mw.Title(mw.forum.toppage).title+'/'),
apnamespace: new mw.Title(mw.forum.toppage).namespace,
apfilterredir: "nonredirects",
aplimit: mw.forum.threads
}).then(async (allpages) => {
return await new mw.Api().get({
action: "parse",
format: "json",
text: `{{#invoke:Thread|main|1=${cont ? '{}' : JSON.stringify(mw.forum.sticky)}|2=${JSON.stringify(allpages.query.allpages)}${cont ? '|3=true' : ''}}}`,
prop: "text",
wrapoutputclass: "",
contentmodel: "wikitext",
formatversion: "2"
}).then((parse) => {
return [parse.parse.text, (allpages.continue ? allpages.continue.apcontinue : undefined)];
});
});
},
preview: function(){
new mw.Api().get({
action: "parse",
format: "json",
text: document.querySelector("#wpTextbox1").value,
prop: "text",
preview: "true",
wrapoutputclass: "",
contentmodel: "wikitext",
disablelimitreport: "1",
formatversion: "2"
}).then((parse) => {
document.querySelector("#f-form > fieldset").hidden = false;
document.querySelector("#f-preview-content").innerHTML = `<div style="white-space:pre;">${parse.parse.text}</div>`;
});
}
};
const mc = document.querySelector('#mw-content-text>.mw-parser-output');
if(mw.config.get('wgPageName') == mw.forum.toppage){
if(mw.util.getParamValue('newthread')=='1'){
mc.innerHTML = msg.createform;
document.querySelector("#f-preview").onclick = func.preview;
mw.loader.using('ext.wikiEditor');
document.querySelector('#f-create').onclick = function(){
new mw.Api().postWithToken('csrf', {
action: 'edit',
title: `${mw.forum.toppage}/${document.querySelector('#f-threadname').value}`,
text: `{{post|${mw.forum.username}|1|{{subst:#timel:Y/m/d H:i}}|4=${document.querySelector('#wpTextbox1').value}}}`,
summary: msg.createthreadsummary,
format: 'json'
}).done(() => {
location.href = `${mw.config.get('wgArticlePath').replace('$1',mw.forum.toppage)}/${document.querySelector('#f-threadname').value}`;
}).fail(() => {
mw.notify(msg.posterror);
});
};
return;
}
mc.innerHTML = msg.loading;
func.getthreads().then((res) => {
mc.innerHTML = res[0] + msg.toppage_css;
if(res[1]){
document.querySelector('#mw-content-text').innerHTML += msg.load_more;
document.querySelector('#f-loadmore').onclick = function(){
func.getthreads(res[1]).then((mres) => {
document.querySelector('#mw-content-text>.mw-parser-output>table>tbody').innerHTML += mres[0];
if(!mres[1]){
document.querySelector('#f-loadmore').remove();
}
});
};
}
});
document.querySelector('.mw-indicators').innerHTML = msg.create;
document.querySelector("#content > .mw-indicators > input").onclick = function(){
const url=new URL(window.location.href);
url.searchParams.set('newthread','1');
location.href=url;
};
}else{
mc.innerHTML += msg.postform;
document.querySelector("#f-preview").onclick = func.preview;
mw.loader.using('ext.wikiEditor');
document.querySelector('.mw-indicators').innerHTML = msg.gotoform;
document.querySelector('#f-post').onclick = (async() => {
document.querySelector('#f-post').disabled = true;
let lp;
await new mw.Api().get({
action: "parse",
format: "json",
text: `{{#invoke:Thread|getinfo|page=${mw.config.get('wgPageName')}|js=true}}`,
prop: "text",
wrapoutputclass: "",
contentmodel: "wikitext",
disablelimitreport: "1",
formatversion: "2"
}).then((parse) => {
lp = Number(parse.parse.text.replace(/<p>(\d+)\n<\/p>/,'$1'))+1;
});
const summary = document.querySelector('#f-reply-cb').checked ? `${msg.postsummary} [[${mw.config.get('wgPageName')}#post-${lp}|#${lp}]] ${msg.replysummary} [[User:${document.querySelector('[id="'+document.querySelector('#f-reply').value+'-user"]').innerText}|${document.querySelector('[id="'+document.querySelector('#f-reply').value+'-user"]').innerText}]]` : `${msg.postsummary} [[${mw.config.get('wgPageName')}#post-${lp}|#${lp}]]`;
new mw.Api().postWithToken('csrf', {
action: 'edit',
title: mw.config.get('wgPageName'),
appendtext: `\n{{post|${mw.forum.username}|${lp}|{{subst:#timel:Y/m/d H:i}}|4=${document.querySelector('#wpTextbox1').value}${document.querySelector('#f-reply-cb').checked ? '|re='+document.querySelector('#f-reply').value : ''}}}`,
summary: summary,
format: 'json'
}).done(() => {
location.reload();
}).fail(() => {
mw.notify(msg.posterror);
});
});
}
return;
})();
// </nowiki>