Comparing version 1.8.0 to 1.9.0
{ | ||
"name": "wikiapi", | ||
"title": "JavaScript MediaWiki API for node.js", | ||
"version": "1.8.0", | ||
"version": "1.9.0", | ||
"description": "A simple way to access MediaWiki API via JavaScript with simple wikitext parser.", | ||
@@ -6,0 +6,0 @@ "keywords": [ "MediaWiki", "MediaWiki API", "wikitext", "ECMAScript 2017", "wikidata", "wdq", "sparql" ], |
172
wikiapi.js
@@ -40,2 +40,4 @@ 'use strict'; | ||
const KEY_wiki = Symbol('wiki'); | ||
//for debug | ||
//wikiapi.KEY_wiki = KEY_wiki; | ||
@@ -75,2 +77,6 @@ /** | ||
const page_data_attributes = { | ||
/** | ||
* {String}page content, maybe undefined. 條目/頁面內容 = | ||
* CeL.wiki.revision_content(revision) | ||
*/ | ||
wikitext: { | ||
@@ -116,2 +122,18 @@ get() { | ||
function reject_edit_error(reject, error, result) { | ||
// skip_edit is not error | ||
if (error && error !== /* 'skip' */ wikiapi.skip_edit[1] | ||
//@see wiki_API_edit.check_data | ||
&& error !== 'empty' && error !== 'cancel') { | ||
if (typeof error === 'string') { | ||
error = new Error(error); | ||
error.from_string = true; | ||
} | ||
if (result && typeof error === 'object') | ||
error.result = result; | ||
reject(error); | ||
return true; | ||
} | ||
} | ||
// for page list, you had better use wiki.for_each_page(page_list) | ||
@@ -126,14 +148,11 @@ function wikiapi_edit_page(title, content, options) { | ||
wiki.edit(content, options, (title, error, result) => { | ||
// skip_edit is not error | ||
if (error && error !== /* 'skip' */ wikiapi.skip_edit[1]) { | ||
if (typeof error === 'string') { | ||
error = new Error(error); | ||
error.from_string = true; | ||
} | ||
if (typeof error === 'object') | ||
error.result = result; | ||
reject(error); | ||
} else { | ||
//console.trace('wikiapi_edit_page: callbacked'); | ||
//console.log(title); | ||
//console.log(wiki.running); | ||
//CeL.set_debug(6); | ||
if (!reject_edit_error(reject, error, result)) { | ||
resolve(title); | ||
} | ||
//console.trace('wikiapi_edit_page: return'); | ||
}); | ||
@@ -257,2 +276,3 @@ } | ||
function wikiapi_list_executor(resolve, reject) { | ||
options = CeL.setup_options(options); | ||
const wiki = this[KEY_wiki]; | ||
@@ -341,3 +361,3 @@ CeL.wiki.list(title, (list/* , target, options */) => { | ||
// To use: | ||
//const KEY_subcategories = Wikiapi.KEY_subcategories; | ||
// const KEY_subcategories = Wikiapi.KEY_subcategories; | ||
@@ -372,11 +392,10 @@ // -------------------------------------------------------- | ||
* @param {Object}[options] | ||
* e.g., { no_message: true, no_warning: true, | ||
* page_options: { redirects: true, rvprop: 'ids|content|timestamp|user' } } | ||
* e.g., { no_edit: true, no_warning: true, page_options: { | ||
* redirects: 1, rvprop: 'ids|content|timestamp|user' } } | ||
*/ | ||
function wikiapi_for_each_page(page_list, for_each_page, options) { | ||
function wikiapi_for_each_page_executor(resolve, reject) { | ||
const promises = []; | ||
const wiki = this[KEY_wiki]; | ||
const promises = []; | ||
// 一次取得多個頁面內容,以節省傳輸次數。 | ||
wiki.work({ | ||
const work_options = { | ||
// log_to: null, | ||
@@ -388,2 +407,9 @@ // no_edit: true, | ||
onerror(error) { | ||
//console.trace('Get error: ' + error); | ||
if (reject_edit_error(reject, error) | ||
&& options && options.onerror) { | ||
options.onerror(error); | ||
} | ||
}, | ||
each(page_data/* , messages, config */) { | ||
@@ -394,12 +420,44 @@ try { | ||
Object.defineProperties(page_data, page_data_attributes); | ||
const result = for_each_page.call(this, page_data | ||
/* , messages, config */); | ||
if (work_options.will_call_methods) { | ||
//** 這邊的操作在 wiki.next() 中會因 .will_call_methods 先執行一次。 | ||
// 因為接下來的操作可能會呼叫 this.next() 本身, | ||
// 因此必須把正在執行的標記消掉。 | ||
//wiki.running = false; | ||
// 每次都設定 `wiki.running = false`,在這會出問題: | ||
// 20200209.「S.P.A.L.」関連ページの貼り換えのbot作業依頼.js | ||
} | ||
const result = for_each_page.apply(this, arguments); | ||
// Promise.isPromise() | ||
if (result && typeof result.then === 'function') { | ||
if (CeL.is_thenable(result)) { | ||
promises.push(result); | ||
} else { | ||
return result; | ||
//https://stackoverflow.com/questions/30564053/how-can-i-synchronously-determine-a-javascript-promises-state | ||
//https://github.com/kudla/promise-status-async/blob/master/lib/promiseState.js | ||
const fulfilled = Object.create(null); | ||
//Promise.race([result, fulfilled]).then(v => { status = v === t ? "pending" : "fulfilled" }, () => { status = "rejected" }); | ||
Promise.race([result, fulfilled]).then(first_fulfilled => { | ||
// wiki.running === true | ||
//console.trace(`wiki.running = ${wiki.running}`); | ||
if (first_fulfilled === fulfilled) { | ||
//assert: result is pending | ||
//e.g., | ||
//await wiki.for_each_page(need_check_redirected_list, ...) | ||
//@ await wiki.for_each_page(vital_articles_list, for_each_list_page, ...) | ||
//@ 20200122.update_vital_articles.js | ||
//console.trace('call wiki.next()'); | ||
wiki.next(); | ||
} | ||
}, () => { /*Do not catch error here.*/ }); | ||
} | ||
// wiki.next() will wait for result.then() calling back if CeL.is_thenable(result). | ||
// e.g., async function for_each_list_page(list_page_data) @ 20200122.update_vital_articles.js | ||
return result; | ||
} catch (e) { | ||
//console.trace('Get error: ' + e); | ||
reject(e); | ||
//re-throw to wiki.work() | ||
//throw e; | ||
} | ||
@@ -409,5 +467,12 @@ }, | ||
last() { | ||
Promise.all(promises).then(resolve).catch(reject); | ||
//警告: 用 Promise.allSettled(promises),result 假如 throw 可能會 catch 不到! | ||
Promise.all(promises) | ||
.then(resolve, reject) | ||
.then(options && typeof options.last === 'function' && options.last.bind(this)); | ||
//console.trace('wikiapi_for_each_page_executor finish:'); | ||
//console.log(options); | ||
} | ||
}, page_list); | ||
}; | ||
// 一次取得多個頁面內容,以節省傳輸次數。 | ||
wiki.work(work_options, page_list); | ||
} | ||
@@ -451,2 +516,48 @@ | ||
// -------------------------------------------------------- | ||
/** | ||
* Get featured content. | ||
* | ||
* @example<code> | ||
// MUST including wiki.featured_content first to get featured content! | ||
CeL.run('application.net.wiki.featured_content'); | ||
... | ||
const FC_data_hash = await wiki.get_featured_content(); | ||
FC_data_hash === wiki.FC_data_hash; | ||
</code> | ||
* | ||
* @param {String|Object}[options] | ||
* {String}type (FFA|GA|FA|FL) or options: | ||
* {type,on_conflict(FC_title, {from,to})} | ||
*/ | ||
function wikiapi_get_featured_content(options) { | ||
if (!options || !options.type) { | ||
const session = this; | ||
let promise = Promise.resolve(); | ||
wikiapi_get_featured_content.default_types.forEach(type => { | ||
promise = promise.then(wikiapi_get_featured_content.bind(session, { ...options, type })); | ||
}); | ||
return promise; | ||
} | ||
function wikiapi_get_featured_content_executor(resolve, reject) { | ||
const wiki = this[KEY_wiki]; | ||
wiki.get_featured_content(options, (FC_data_hash) => { | ||
try { | ||
this.FC_data_hash = FC_data_hash; | ||
resolve(FC_data_hash); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}); | ||
} | ||
return new Promise(wikiapi_get_featured_content_executor.bind(this)); | ||
} | ||
wikiapi_get_featured_content.default_types = 'FFA|GA|FA|FL'.split('|'); | ||
// -------------------------------------------------------- | ||
// exports | ||
@@ -468,2 +579,4 @@ | ||
get_featured_content: wikiapi_get_featured_content, | ||
for_each_page: wikiapi_for_each_page, | ||
@@ -478,2 +591,13 @@ | ||
// wrapper for sync functions | ||
for (let function_name of ('namespace|remove_namespace|is_namespace|to_namespace|is_talk_namespace|to_talk_page|talk_page_to_main|normalize_title' | ||
//CeL.run('application.net.wiki.featured_content'); | ||
//[].map(wiki.to_talk_page.bind(wiki)) | ||
+ '|get_featured_content_configurations').split('|')) { | ||
wikiapi.prototype[function_name] = function wrapper() { | ||
const wiki = this[KEY_wiki]; | ||
return wiki[function_name].apply(wiki, arguments); | ||
}; | ||
} | ||
for (let type of CeL.wiki.list.type_list) { | ||
@@ -484,3 +608,3 @@ // Can not use `= (title, options) {}` ! | ||
wikiapi.prototype[type] = function (title, options) { | ||
var _this = this; | ||
const _this = this; | ||
/** | ||
@@ -487,0 +611,0 @@ * @example <code> |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
38025
864