You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
5.3 KiB
JavaScript

const Vue = require("vue");
class BasePageListLoader {
loadPageList() {
return Promise.reject(new Error('Not implemented'));
}
parseHTMLString(txt) {
try {
let parser = new DOMParser();
let xmlDoc = parser.parseFromString(txt, "text/html");
return xmlDoc;
} catch(e) {
console.error(e.message);
}
return null;
}
loadPageContent(pageInfo) {
return new Promise((resolve, reject) => {
if (!pageInfo || !pageInfo.fullTitle) {
return reject(new Error('pageInfo.fullTitle is null'));
}
let url = mw.util.getUrl(pageInfo.fullTitle);
if (url.indexOf('?') >= 0) {
url += '&';
} else {
url += '?'
}
url += 'action=render';
$.get(url, (str) => {
let $dom = $(this.parseHTMLString(str));
let $content = $dom.find('.mw-parser-output');
if ($content.length > 0) {
//删除目录
$content.find('.toc').remove();
resolve($content.html());
}
}, 'html');
});
}
getPageUrl(pageInfo) {
return new Promise((resolve, reject) => {
if (!pageInfo || !pageInfo.fullTitle) {
return reject(new Error('pageInfo.fullTitle is null'));
}
let url = mw.util.getUrl(pageInfo.fullTitle);
resolve(url);
});
}
/**
* 根据标题生成页面信息
* @param {string} title
* @returns
*/
makePageInfoFromTitle(title) {
let pageInfo = {
fullTitle: title,
title: title,
subTitle: null
};
if (title.indexOf('/') !== 0) {
let splitPos = title.lastIndexOf('/');
pageInfo.title = title.substring(splitPos + 1);
pageInfo.subTitle = title.substring(0, splitPos);
}
return pageInfo;
}
}
class PresetPageListLoader extends BasePageListLoader {
/**
* 从页面列表加载页面
* @param {string[]} pageList
*/
constructor(pageList) {
super();
this.pageList = pageList.map((pageTitle) => {
return this.makePageInfoFromTitle(pageTitle);
});
}
/**
* 加载页面列表
* @returns {Promise<*>}
*/
loadPageList() {
return Promise.resolve(this.pageList);
}
}
class CategoryPageListLoader extends BasePageListLoader {
/**
* 从分类加载页面
* @param {string} category
*/
constructor(category) {
super();
this.category = category;
this.api = new mw.Api();
}
/**
* 加载页面列表
* @returns {Promise<*>}
*/
loadPageList() {
return new Promise((resolve, reject) => {
this.api.get({
action: 'query',
list: 'categorymembers',
cmtitle: this.category,
cmtype: 'page',
cmnamespace: 0,
cmlimit: 200,
cmsort: 'sortkey',
}).done((data) => {
if(data.query && data.query.categorymembers){
let pageList = data.query.categorymembers.map((pageInfo) => {
return this.makePageInfoFromTitle(pageInfo.title);
});
resolve(pageList);
} else if(data.error){
reject(new Error(data.error.info));
} else {
reject(new Error(mw.message('isekai-discover-error-cannotload').parse()));
}
}).fail((data) => {
reject(new Error(data.error.info));
});
});
}
}
function htmlDecode(input) {
var doc = new DOMParser().parseFromString(input, "text/html");
return doc.documentElement.textContent;
}
let previewPageList = document.querySelectorAll('.isekai-preview-page-list-card');
if (previewPageList.length > 0) {
const App = require("./PreviewPageList.vue");
previewPageList.forEach((previewPageListDom) => {
try {
let props = {};
let dataset = previewPageListDom.dataset;
props.autoFocus = (dataset.autofocus == '1');
props.lazyLoad = (dataset.lazyload == '1');
switch (dataset.loader) {
case 'pages':
let pagesJsonEl = document.querySelector('script[type="application/json"][data-pages]');
let pageList = [];
if (pagesJsonEl) {
let jsonStr = htmlDecode(pagesJsonEl.innerText);
pageList = JSON.parse(jsonStr);
}
props.pageListLoader = new PresetPageListLoader(pageList);
break;
case 'category':
let category = dataset.category;
props.pageListLoader = new CategoryPageListLoader(category);
break;
default:
console.error('Unknown loader: ' + dataset.loader);
}
Vue.createMwApp(App, props).mount(previewPageListDom);
} catch (e) {
console.error(e);
}
});
}