mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/SyntaxHighlight_GeSHi
synced 2024-11-27 15:50:37 +00:00
Implement copy buttons for code blocks
<syntaxhighlight> blocks with a boolean "copy" param will now have a button next to them for copying the code to the clipboard. Not applicable for inline code blocks. Adapted from the mediawiki.org gadget written by Krinkle. Bug: T40932 Change-Id: Ic8ef030514c3b6dd2cb9b137f032588869ab3762
This commit is contained in:
parent
f2d0dde88c
commit
55630cc5ea
|
@ -41,7 +41,15 @@
|
|||
"ext.pygments.view": {
|
||||
"scripts": [
|
||||
"pygments.linenumbers.js",
|
||||
"pygments.links.js"
|
||||
"pygments.links.js",
|
||||
"pygments.copy.js"
|
||||
],
|
||||
"styles": [
|
||||
"pygments.copy.css"
|
||||
],
|
||||
"messages": [
|
||||
"syntaxhighlight-button-copy",
|
||||
"syntaxhighlight-button-copied"
|
||||
],
|
||||
"dependencies": [
|
||||
"mediawiki.util"
|
||||
|
|
|
@ -20,5 +20,7 @@
|
|||
"syntaxhighlight-visualeditor-mwsyntaxhighlightinspector-title": "Code block",
|
||||
"syntaxhighlight-error-pygments-invocation-failure": "Failed to invoke Pygments",
|
||||
"syntaxhighlight-error-unknown-language": "Unknown language \"$1\"",
|
||||
"syntaxhighlight-error-exceeds-size-limit": "Code size of $1 {{PLURAL:$1|bytes}} exceeds allowed maximum of $2 {{PLURAL:$2|bytes}}"
|
||||
"syntaxhighlight-error-exceeds-size-limit": "Code size of $1 {{PLURAL:$1|bytes}} exceeds allowed maximum of $2 {{PLURAL:$2|bytes}}",
|
||||
"syntaxhighlight-button-copy": "Copy",
|
||||
"syntaxhighlight-button-copied": "Copied!"
|
||||
}
|
||||
|
|
|
@ -29,5 +29,7 @@
|
|||
"syntaxhighlight-visualeditor-mwsyntaxhighlightinspector-title": "Title for the VisualEditor syntax highlighter inspector, above the text area for the code",
|
||||
"syntaxhighlight-error-pygments-invocation-failure": "Error message shown when the syntax highlighting library failed with an unspecified error",
|
||||
"syntaxhighlight-error-unknown-language": "Error message shown when the programming language name was not recognized by the syntax highlighting library. Parameters:\n* $1 - the language name",
|
||||
"syntaxhighlight-error-exceeds-size-limit": "Error message shown when the block of code to be highlighted exceeds the size limit. Parameters:\n* $1 - the size of the code block, in bytes\n* $2 - the maximum size allowed, in bytes."
|
||||
"syntaxhighlight-error-exceeds-size-limit": "Error message shown when the block of code to be highlighted exceeds the size limit. Parameters:\n* $1 - the size of the code block, in bytes\n* $2 - the maximum size allowed, in bytes.",
|
||||
"syntaxhighlight-button-copy": "Label for button to copy the highlighted code",
|
||||
"syntaxhighlight-button-copied": "Label shown when the highlighted code has been copied"
|
||||
}
|
||||
|
|
|
@ -387,6 +387,7 @@ class SyntaxHighlight extends ExtensionTagHandler implements
|
|||
* If it contains a 'inline' key, the output will not be wrapped in `<div><pre/></div>`.
|
||||
* If it contains a 'linelinks' key, lines will have links and anchors with a prefix
|
||||
* of the value. Similar to the lineanchors+linespans features in Pygments.
|
||||
* If it contains a 'copy' key, a link will be shown for copying content to the clipboard.
|
||||
* @param Parser|null $parser Parser, if generating content to be parsed.
|
||||
* @return Status Status object, with HTML representing the highlighted
|
||||
* code as its value.
|
||||
|
@ -440,6 +441,9 @@ class SyntaxHighlight extends ExtensionTagHandler implements
|
|||
if ( $showLines ) {
|
||||
$classList[] = self::HIGHLIGHT_CSS_CLASS . '-lines';
|
||||
}
|
||||
if ( !$isInline && isset( $args['copy'] ) ) {
|
||||
$classList[] = 'mw-highlight-copy';
|
||||
}
|
||||
$htmlAttribs['class'] = implode( ' ', $classList );
|
||||
$htmlAttribs['dir'] = $dir;
|
||||
'@phan-var array{class:string,dir:string} $htmlAttribs';
|
||||
|
|
38
modules/pygments.copy.css
Normal file
38
modules/pygments.copy.css
Normal file
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Adapted from https://www.mediawiki.org/wiki/MediaWiki:Gadget-site-tpl-copy.css
|
||||
* Original author: Krinkle
|
||||
*/
|
||||
|
||||
.mw-highlight-copy {
|
||||
position: relative;
|
||||
min-width: 40%;
|
||||
max-width: max-content;
|
||||
}
|
||||
|
||||
/**
|
||||
* https://doc.wikimedia.org/oojs-ui/master/demos/ (2023-11-13)
|
||||
* https://design.wikimedia.org/style-guide/components/buttons.html
|
||||
*/
|
||||
.mw-highlight-copy--bound button {
|
||||
position: absolute;
|
||||
top: -1em;
|
||||
right: -0.9em;
|
||||
box-sizing: border-box;
|
||||
padding: 5px 7px;
|
||||
border-radius: 2px;
|
||||
background: #fff;
|
||||
color: #36c;
|
||||
border: 1px solid #eaecf0;
|
||||
}
|
||||
|
||||
.mw-highlight-copy--bound button:hover {
|
||||
cursor: pointer;
|
||||
background: #fff;
|
||||
border: 1px solid #447ff5;
|
||||
}
|
||||
|
||||
.mw-highlight-copy--bound button:active {
|
||||
background: #eff3fa;
|
||||
color: #2a4b8d;
|
||||
border-color: #2a4b8d;
|
||||
}
|
35
modules/pygments.copy.js
Normal file
35
modules/pygments.copy.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Adapted from https://www.mediawiki.org/wiki/MediaWiki:Gadget-site-tpl-copy.js
|
||||
* Original author: Krinkle
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line compat/compat
|
||||
const hasFeature = navigator.clipboard && 'writeText' in navigator.clipboard;
|
||||
if ( hasFeature ) {
|
||||
// Add type=button to avoid form submission in preview
|
||||
const $btn = $( '<button>' )
|
||||
.attr( 'type', 'button' )
|
||||
.text( mw.msg( 'syntaxhighlight-button-copy' ) )
|
||||
.on( 'click', function () {
|
||||
const btn = this;
|
||||
const wrapper = btn.closest( '.mw-highlight-copy' );
|
||||
const preNode = wrapper && wrapper.querySelector( 'pre' );
|
||||
const content = preNode && preNode.textContent.trim();
|
||||
try {
|
||||
navigator.clipboard.writeText( content );
|
||||
} catch ( e ) {
|
||||
return;
|
||||
}
|
||||
const prevLabel = btn.textContent;
|
||||
btn.textContent = mw.msg( 'syntaxhighlight-button-copied' );
|
||||
setTimeout( () => {
|
||||
btn.textContent = prevLabel;
|
||||
}, 5000 );
|
||||
} );
|
||||
|
||||
mw.hook( 'wikipage.content' ).add( ( $content ) => {
|
||||
$content.find( '.mw-highlight-copy:not(.mw-highlight-copy--bound)' )
|
||||
.append( $btn.clone( true ) )
|
||||
.addClass( 'mw-highlight-copy--bound' );
|
||||
} );
|
||||
}
|
Loading…
Reference in a new issue