User:Andrybak/Scripts/copy-section-link.js
Appearance
< User:Andrybak | Scripts
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
This user script seems to have a documentation page at User:Andrybak/Scripts/copy-section-link. |
// 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/w/index.php?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;
}
/*
* See [[Module:Section link#L-11--L-15]]
*/
function escapeHash(hash) {
return hash
.replaceAll('{', '{')
.replaceAll('}', '}');
}
/*
* 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.append($( "<a>", { "class": "copy-section-link-pilcrow" } )
.text( "¶" )
.click( function () {
if( popup === null ) {
const hash = escapeHash(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( ".copy-section-link-pilcrow" +
"{ display: none; margin-left: 1em; font-size: initial; }" +
".mw-heading:hover .copy-section-link-pilcrow, " +
"h1:hover .copy-section-link-pilcrow, h2:hover .copy-section-link-pilcrow, h3:hover .copy-section-link-pilcrow," +
"h4:hover .copy-section-link-pilcrow, h5:hover .copy-section-link-pilcrow, h6:hover .copy-section-link-pilcrow" +
"{ display: inline; }" +
".copy-section-link-pilcrow + .oo-ui-widget" +
"{ font-weight: normal; }" );
} );
// </nowiki>