Jump to content

User:Sophivorus/comparator.js

From Appropedia

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.
const Comparator = {

	init( $content ) {
		$content.find( '.template-compare' ).each( Comparator.makeTable );
	},

	async makeTable() {
		// Load WikitextParser.js
		// See https://www.mediawiki.org/wiki/WikitextParser.js
		await mw.loader.getScript( '//www.mediawiki.org/w/index.php?title=MediaWiki:Gadget-Global-WikitextParser.js&action=raw&ctype=text/javascript' );

		// Make the Vue app
		const require = await mw.loader.using( '@wikimedia/codex' );
		const Vue = require( 'vue' );
		const Codex = require( '@wikimedia/codex' );
		const app = Vue.createMwApp( Comparator.rootComponent, this.dataset );
		app.component( 'cdx-table', Codex.CdxTable );
		app.mount( this );
	},

	rootComponent: {

		props: [ 'seed' ],

		template: `<cdx-table
			:caption="caption"
			:columns="columns"
			:data="data"
			v-model:sort="sort"
			@update:sort="onSort"
		>
			<template #item-title="{ item }">
				<span v-html="item"></span>
			</template>
		</cdx-table>`,

		data() {
			return {
				caption: this.seed,
				columns: [
					{ id: 'title', label: 'Title', allowSort: true },
					{ id: 'language', label: 'Language', allowSort: true },
					{ id: 'lead', label: 'Lead', allowSort: true },
					{ id: 'image', label: 'Image', allowSort: true },
					{ id: 'length', label: 'Length', allowSort: true },
					{ id: 'sections', label: 'Sections', allowSort: true },
					{ id: 'images', label: 'Images', allowSort: true },
					{ id: 'links', label: 'Links', allowSort: true },
					{ id: 'editors', label: 'Editors', allowSort: true },
					{ id: 'references', label: 'References', allowSort: true },
				],
				data: [],
				sort: {},
			};
		},

		async mounted() {
			const titles = [];

			const seed = this.seed;
			const seedTitle = new mw.Title( seed );

			// Category
			if ( seedTitle.getNamespaceId() === 14 ) {
				const query = {
					action: 'query',
					list: 'categorymembers',
					cmlimit: 'max',
					cmtitle: seedTitle.getPrefixedText(),
					formatversion: 2,
				};
				const result = await new mw.Api().get( query );
				for ( const categorymember of result.query.categorymembers ) {
					titles.push( categorymember.title );
				}
			}

			for ( const title of titles ) {
				const query = {
					action: 'query',
					titles: title,
					prop: 'info|images|links|contributors|revisions|pageimages',
					imlimit: 'max',
					pllimit: 'max',
					pclimit: 'max',
					piprop: 'name',
					rvprop: 'content',
					rvslots: 'main',
					formatversion: 2,
				};
				const result = await new mw.Api().get( query );
				const page = result.query.pages[0];
				const wikitext = page.revisions[0].slots.main.content;

				// Determine if there's lead text
				let leadWikitext = WikitextParser.getLeadSection( wikitext );
				const leadTemplates = WikitextParser.getTemplates( leadWikitext );
				for ( const leadTemplate of leadTemplates ) {
					leadWikitext = leadWikitext.replace( leadTemplate, '' );
				}
				const leadFiles = WikitextParser.getFiles( leadWikitext );
				for ( const leadFile of leadFiles ) {
					leadWikitext = leadWikitext.replace( leadFile, '' );
				}

				// Determine the number of sections
				const sectionTitles = WikitextParser.getSectionTitles( wikitext );

				// Determine the number of references
				const references = WikitextParser.getReferences( wikitext );

				// Build the title link
				const titleObject = new mw.Title( page.title );
				const titleUrl = titleObject.getUrl();
				const titleLink = '<a target="_blank" href="' + titleUrl + '">' + page.title + '</a>';

				const data = {
					title: titleLink,
					language: page.pagelanguage,
					lead: leadWikitext ? 'Yes' : 'No',
					image: page.pageimage ? 'Yes' : 'No',
					length: page.length,
					sections: sectionTitles.length,
					images: page.images && page.images.length || 0,
					links: page.links && page.links.length || 0,
					editors: page.contributors && page.contributors.length || 0,
					references: references.length,
				};
				this.data.push( data );
			}
		},

		methods: {

			onSort( newSort ) {
				this.sort = newSort;
				const sortKey = Object.keys( newSort )[0];
				const sortOrder = newSort[ sortKey ];

				function sortNumerically( data, columnId, sortDir ) {
					return data.sort( ( a, b ) => {
						if ( sortDir === 'asc' ) {
							return b[ columnId ] - a[ columnId ];
						}
						return a[ columnId ] - b[ columnId ];
					} );
				}

				function sortAlphabetically( data, columnId, sortDir ) {
					return data.sort( ( a, b ) => {
						const multiplier = sortDir === 'asc' ? 1 : -1;
						return multiplier * ( a[ columnId ].localeCompare( b[ columnId ] ) );
					} );
				}

				// Sort data
				switch ( sortKey ) {
					case 'title':
					case 'language':
					case 'lead':
					case 'image':
						this.data = sortAlphabetically( this.data, sortKey, sortOrder );
						break;
					case 'length':
					case 'sections':
					case 'images':
					case 'links':
					case 'editors':
					case 'references':
						this.data = sortNumerically( this.data, sortKey, sortOrder );
						break;
				}
			}
		}
	}
};

mw.hook( 'wikipage.content' ).add( Comparator.init );
Cookies help us deliver our services. By using our services, you agree to our use of cookies.