User:Sophivorus/ExcerptTree.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/**
 * ExcerptTree is a script to view and navigate excerpt trees in Wikipedia
 * Author/Maintainer: Sophivorus
 * Expected use will be via ?withJS links, so may not appear in what-links-here
 */
var ExcerptTree = {

	/**
	 * Initialization script
	 */
	init: function () {
		$( '.ExcerptTree' ).show();
		$( '.ExcerptTree li' ).each( ExcerptTree.addChildren );
	},

	addChildren: function () {
		var node = $( this ),
			title = $( node ).children( 'a' ).attr( 'title' );
		ExcerptTree.getChildren( title ).done( function ( data ) {
			//console.log( data );
			var content = data.query.pages[0].revisions[0].slots.main.content;
			var matches = [...content.matchAll( /{{ *[Ee]xcerpt *\| *([^}]+) *}}/g )];
			//console.log( matches );
			if ( matches.length ) {
				ExcerptTree.addButton( node );
				var list = $( '<ul>' ).hide().data( 'virgin', true );
				matches.forEach( function ( match ) {
					var params = match[1].split( '|' ).filter( param => /=/.test( param ) === false ); // Remove all named params
					var title = params[0].split( '#' )[0];
					title = title.charAt(0).toUpperCase() + title.slice(1); // Capitalize the title
					var section = params[0].split( '#' )[1] || params[1];
					var text = section ? title + ' § ' + section : title;
					var href = mw.util.getUrl( ( section ? title + '#' + section : title ) );
					var link = $( '<a>', { 'href': href, 'title': title } ).text( text );
					var item = $( '<li>' ).html( link );
					list.append( item );
				});
				node.append( list );
			}
		});
	},

	/**
	 * Add a clickable right-arrow to the given node
	 */
	addButton: function ( node ) {
		var button = $( '<span>' ).text( '►' ).css({
			'cursor': 'pointer',
			'position': 'absolute',
			'left': '-1em'
		});
		node.css({
			'list-style': 'none',
			'position': 'relative'
		}).prepend( button );
		button.click( node, ExcerptTree.toggleChildren );
	},

	toggleChildren: function ( event ) {
		var node = event.data,
			button = $( node ).children( 'span' ),
			list = $( node ).children( 'ul' ),
			virgin = list.data( 'virgin' );

		list.toggle();
		if ( virgin ) {
			list.data( 'virgin', false );
			list.children( 'li' ).each( ExcerptTree.addChildren );
			button.text( '▼' );
		} else {
			if ( list.is( ':visible' ) ) {
				button.text( '▼' );
			} else {
				button.text( '►' );
			}
		}
	},

	getChildren: function ( title ) {
		var api = new mw.Api();
		return api.get( {
			titles: title,
			action: 'query',
			formatversion: 2,
			prop: 'revisions',
			rvprop: 'content',
			rvslots: 'main',
			redirects: true
		} );
	}
};

mw.loader.using( 'mediawiki.api', ExcerptTree.init );