MediaWiki:Gadget-InitListingTools.js
注意: 保存後、変更を確認するにはブラウザーのキャッシュを消去する必要がある場合があります。
- Firefox / Safari: Shift を押しながら 再読み込み をクリックするか、Ctrl-F5 または Ctrl-R を押してください (Mac では ⌘-R)
- Google Chrome: Ctrl-Shift-R を押してください (Mac では ⌘-Shift-R)
- Microsoft Edge: Ctrl を押しながら 最新の情報に更新 をクリックするか、Ctrl-F5 を押してください。
//<nowiki>
/** initListingTools v2.0-ja, 2024-07-19
Initialization of listing editor and listing info
Original author: Roland Unger
Additional contributor: Tmv
Support of desktop and mobile views
Documentation: in preparation
License: GPL-2.0+, CC-by-sa 3.0
*/
let table = await ( async ( $, mw ) => {
'use strict';
let initListingTools = (() => {
// options for module import
let options = [
{
page: 'Module:Marker utilities/Types', // name of module to import
index: 'type', // name of key field
start: /^.*types *= *{/g, // to remove from start
end: /,? *},? *} *$/g, // to remove at the end
label: 'label', // second sort key
alias: 'alias', // alias for index
arrayName: 'types', // name of the new array
defaultArray: [
{ 'type': 'area', group: 'area', label: '地域' },
{ 'type': 'buy', group: 'buy', label: '買う' },
{ 'type': 'do', group: 'do', label: 'する' },
{ 'type': 'drink', group: 'drink', label: '飲む' },
{ 'type': 'eat', group: 'eat', label: '食べる' },
{ 'type': 'go', group: 'go', label: '行く' },
{ 'type': 'other', group: 'other', label: 'その他' },
{ 'type': 'populated', group: 'populated', label: '都市' },
{ 'type': 'see', group: 'see', label: '観る' },
{ 'type': 'sleep', group: 'sleep', label: '泊まる' },
{ 'type': 'view', group: 'view', label: '眺める' },
]
},
{
page: 'Module:Marker utilities/Groups',
index: 'group',
start: /^.*groups *= *{/g,
end: /,? *},? *} *$/g,
label: 'label',
alias: 'alias',
arrayName: 'groups',
defaultArray: [
{ group: 'area', label: '地域', color: '#0000FF' },
{ group: 'buy', label: '買う', color: '#008080' },
{ group: 'do', label: 'する', color: '#808080' },
{ group: 'drink', label: '飲む', color: '#000000' },
{ group: 'eat', label: '食べる', color: '#D2691E' },
{ group: 'go', label: '行く', color: '#A52A2A' },
{ group: 'other', label: 'その他', color: '#228B22' },
{ group: 'populated', label: '都市', color: '#0000FF' },
{ group: 'see', label: '観る', color: '#4682B4' },
{ group: 'sleep', label: '泊まる', color: '#000080' },
{ group: 'view', label: '眺める', color: '#4169E1' },
]
},
{
page: 'Module:VCard/Subtypes',
index: 'type',
start: /^.* f *= *{/g,
end: /,? *} *, *g *=.*$/g,
sortKey: 'sortkey', // first sort key
label: 'n', // second sort key
arrayName: 'subtypes',
defaultArray: [
{ 'type': 'budget', g: 1, w: '', n: '', f: '' },
{ 'type': 'midrange', g: 1, w: '', n: '', f: '' },
{ 'type': 'upmarket', g: 1, w: '', n: '', f: '' },
]
},
{
page: 'Module:VCard/Cards',
index: '', // only import, no rearranging
start: /^.*cards *= *{/g,
end: /,? *},? *} *$/g,
arrayName: 'payments',
defaultArray: {}
},
{
page: 'Module:Hours/i18n',
index: '',
start: /^.*dateIds *= *{/g,
end: /,? *},? *} *$/g,
arrayName: 'hours',
defaultArray: {}
},
{
page: 'Module:VCard/Qualifiers',
index: '',
start: /^.*labels *= *{/g,
end: /,? *},? *} *$/g,
arrayName: 'qualifiers',
defaultArray: {}
},
{
page: 'Module:CountryData/Currencies',
index: '',
start: /^.*currencies *= *{/g,
end: /,? *} *, *isoToQid *=.*$/g,
arrayName: 'currencies',
defaultArray: {}
}
];
// data: data array from module
// item: single item from options array
// isDefault: data are defaults from options array
let analyzeAndCopyData = ( data, item, isDefault ) => {
let i, dataItem;
// adding missing label from index
for ( i = 0; i < data.length; i++ ) {
dataItem = data[ i ];
dataItem[ item.label ] = dataItem[ item.label ] || '';
if ( dataItem[ item.label ] === '' ) {
if ( typeof dataItem[ item.alias ] === 'undefined' )
dataItem[ item.label ] = dataItem[ item.index ].replace( /_/g, ' ' );
else
if ( typeof( dataItem[ item.alias ] ) === 'string' )
dataItem[ item.label ] = dataItem[ item.alias ].replace( /_/g, ' ' );
else if ( dataItem[ item.alias ][ 0 ] )
dataItem[ item.label ] = dataItem[ item.alias ][ 0 ].replace( /_/g, ' ' );
}
}
// sorting by label in alphabetic order
data.sort( ( a, b ) => {
if ( item.sortKey ) {
a = a[ item.sortKey ] || a[ item.label ];
b = b[ item.sortKey ] || b[ item.label ];
} else {
a = a[ item.label ];
b = b[ item.label ];
}
return a.localeCompare( b );
} );
// copying
if ( isDefault ) {
// copy only if window.ListingEditor.array is empty
if ( typeof window.ListingEditor[ item.arrayName ] === 'undefined' ||
window.ListingEditor[ item.arrayName ].length < 1 ) {
window.ListingEditor[ item.arrayName ] = [].concat( data );
}
} else {
window.ListingEditor[ item.arrayName ] = [].concat( data );
}
return data;
};
// item: item from options array
let getDataFromSingleModule = item => {
return $.ajax( {
type: 'GET',
url: mw.util.wikiScript( '' ),
data: { title: item.page, action: 'raw', ctype: 'text/plain' },
timeout: 3000,
dataType: 'text'
} ).then( data => {
data = data.replace( /\-\-.*\n/g, '' ) // remove comments
.replace( /[\s+\t+]/gm, ' ' ); // remove line breaks and tabs
if ( item.index !== '' )
// convert to (sortable) array
data = data.replace( item.start, '[' ) // delete beginning
.replace( item.end, ']' ) // delete end
.replace( /([,{]) *(wd|alias) *= *\{([^}]*)\}/g, '$1 "$2": [$3]' )
.replace( /( *\[ *")([\w\-]+)(" *\] *= *\{)/g, '{ "' + item.index + '": "$2", ' )
.replace( /( *)([\w\-]+)( *= *\{)/g, '{ "' + item.index + '": "$2", ' )
.replace( /(, *)([\w\-]+)( *=)/g, ', "$2":' );
else
// keep as object
data = data.replace( item.start, '{' ) // delete beginning
.replace( item.end, '}' ) // delete end
.replace( /( *\[ *")([\w\-]+)(" *\] *= *)/g, '"$2":' )
.replace( /([,\{]) *([\w\-]+)( *=)/g, '$1 "$2":' );
// check if data string is valid JSON
let isDefault = false, json, fmtData;
try {
json = JSON.parse( data );
} catch ( e ) {
// invalid JSON
json = item.defaultArray;
isDefault = true;
let pos = e.message.match( /column (\d+) of/i )[ 1 ];
pos = data.substring( pos - 10, pos + 10 );
console.log( e.message + ', data: ' + item.page + ', text: ' + pos );
}
if ( item.index !== '' )
fmtData = analyzeAndCopyData( json, item, isDefault );
else
fmtData = json;
window.ListingEditor[ item.arrayName ] = json;
let dataObj = {}; dataObj[ item.arrayName ] = fmtData;
return dataObj;
} ).catch( () => {
let json = item.defaultArray, fmtData;
if ( item.index !== '' )
fmtData = analyzeAndCopyData( json, item, true );
else
fmtData = json;initListingToolsvar;
window.ListingEditor[ item.arrayName ] = json;
let dataObj = {}; dataObj[ item.arrayName ] = fmtData;
return dataObj;
} );
};
let getDataFromModules = async () => {
let i, allData = {};
// mw already exists but maybe not the ListingEditor object
if ( typeof window.ListingEditor === 'undefined' )
window.ListingEditor = {};
for ( i = 0; i < options.length; i++ )
Object.assign(allData, await getDataFromSingleModule( options[ i ] ));
return allData;
};
let init = async () => {
return await getDataFromModules();
};
return { init: init };
})();
return await initListingTools.init();
})( jQuery, mediaWiki );
module.exports = table;
// </nowiki>