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.

// Fixed version of [[User:Enterprisey/copy-section-link.js]]

// <nowiki>

$.when(

    $.ready,

    mw.loader.using(  "mediawiki.util", "oojs-ui-core", "oojs-ui-widgets"  )

).then( function () {

	/*

	 * The convoluted function is needed, because there are different HTML

	 * layouts for "headings" in different skins.

	 * In Vector 2022, layout of ==Second level== versus ===Third level===

	 * headings is different even for a _single_ skin.

	 *

	 * The HTML layout is either

	 *    <div><h*></h*><edit section link /></div>

	 * or

	 *    <h*><edit section link /></h*>

	 *

	 * For details, see:

	 *   - https://www.mediawiki.org/?title=Heading_HTML_changes&oldid=6538029

	 */

	// Returns a plain HTMLElement

	function findEditSectionForHeader(header) {

		// in Vector, the bracketed [edit] section link is a direct child element/node

		const maybeVectorEditSection = header.querySelector('.mw-editsection');

		if (maybeVectorEditSection) {

			return maybeVectorEditSection;

		}

		// in other skins, the bracketed [edit] section link is a sibling of <h2> <h3> etc

		if (header.parentElement.classList.contains('mw-heading')) {

			const maybeEditSection = header.parentElement.querySelector('.mw-editsection');

			if (maybeEditSection) {

				return maybeEditSection;

			}

		}

		return null;

	}

	/*

	 * The search for all section headings starts with

	 * finding all <h*> tags, which aren't for the table of contents.

	 * From the <h*> tags, we find the "[edit] section links".

	 */

	const allHeaders = $("#mw-content-text .mw-parser-output").find(":header").filter(':not(#mw-toc-heading)');



    allHeaders.each( function(i, header) {

        var popup = null;

        var editSection = findEditSectionForHeader(header);

        let target;

        if (editSection === null) {

        	target = $(header);

        	console.warn('[copy-section-link]', 'edit section link not found:', target);

        } else {

        	target = $(editSection);

        }

        target.after($( "<a>", { "class": "copy-section-link-pilcrow" } )

                .text( "¶" )

                .click( function () {

                    if( popup === null ) {

                        const hash = header.id ? header.id : header.querySelector('.mw-headline')?.id;

                        var oldid = mw.util.getParamValue( "oldid" );

                        var popupContent;

                        function makeContent( pageName, id ) {

                            var wikitext = (pageName + "#" + hash).replace( /_/g, " " );

                            if( !window.copySectionLinkNoSquareBrackets ) {

                               wikitext = '[[' + wikitext + ']]';

                            }

                            return $( '<p>', { "class": "copy-section-link-content" } ).append(

                                $( "<code>", { "id": "copy-section-wikilink" + id } ).text( wikitext ),

                                $( "<button>" )

                                    .text( "Copy" )

                                    .css( { "padding": "0.5em", "cursor": "pointer", "margin-left": "0.5em" } )

                                    .click( function () {

                                        var textField = $( this ).prev();

                                        try {

                                            navigator.clipboard.writeText( textField.text() );

                                        } catch( e ) {

                                            textField.select();

                                            document.execCommand( "copy" );

                                        }

                                    } ),

                                $( "<br>" ),

                                $( "<a>" )

                                	.attr( "href", mw.util.getUrl( pageName ) + "#" + encodeURIComponent( hash ) )

                                	.text( "external" )

                            );

                        }



                        var generalCss = { 'font-size': '0.9rem', 'font-family': 'sans-serif' };



                        var index;

                        if( oldid ) {

                            popupContent = makeContent( "Special:Permalink/" + oldid );

                            popupContent.css( generalCss );

                            popupContent.css( { 'padding-top': '0.5em', 'font-weight': 'normal' } );

                        } else {

                            var normalPanel = new OO.ui.TabPanelLayout( 'normal', {

                                label: 'Link',

                                $content: makeContent( mw.config.get( 'wgPageName' ), 'normal' )

                            } );

                            var permalinkPanel = new OO.ui.TabPanelLayout( 'permalink', {

                                label: 'Permalink',

                                $content: makeContent( 'Special:Permalink/' + mw.config.get( 'wgCurRevisionId' ), 'permalink' )

                            } );

                            index = new OO.ui.IndexLayout();

                            index.addTabPanels(  normalPanel, permalinkPanel  );

                            popupContent = index.$element;

                        }

                        popup = new OO.ui.PopupWidget( {

                            $content: popupContent,

                            $floatableContainer: $( this ),

                            padded: true,

                            width: 400,

                            height: 190,

                            align: 'forwards',

                        } );

                        $( this ).after( popup.$element );

                        if( index ) {

                            index.$menu.find( 'span.oo-ui-labelElement-label' ).css( generalCss );

                            index.$content.css( generalCss );

                        }



                        popup.toggle( true );

                    } else {

                        popup.toggle();

                    }

                } ) );

    } );

    mw.util.addCSS( ".mw-heading .copy-section-link-pilcrow" +

                        "{ display: none; margin-left: 1em; }" +

                    ".mw-heading:hover .copy-section-link-pilcrow" +

                        "{ display: inline; }" +

                    ".mw-heading .copy-section-link-pilcrow + .oo-ui-widget" +

                        "{ font-weight: normal; }" );

} );

// </nowiki>