Introducing a Copy Code Button Plugin for TiddlyWiki: Enhancing Code Sharing and Efficiency

Thank you for the plugin @oeyoews. Am I right that it is the first plugin that does that?

Is the plugin supposed to be also usable independently of neotw or its components?

I tried it on an empty tw with the following results (without/with highlight.js plugin):
without-hjs with-hjs
The tiny button does work.

The styles are written using tailwindcss, and the icons are supported by iconify

tailwindcss plugin: tailwindcss plugin
iconify plugin: iconify

ps: It is completely possible not to rely on additional plug-ins, it just requires extra time, and I don’t plan to do so for the time being.

I’m trying to rework it so that it doesn’t have any dependencies.
@oeyoews do you by any chance still have the non-uglified version of the JS in the rewritten $:/core/modules/widgets/codeblock.js?
This would make things much easier.

Anyway, I have achieved a reasonable result already:

I’ll share it soon after I refine it a bit.

1 Like

I have modified the plugin to simplify it and remove dependencies. See demo here.

Result:

The copy button is highlighted when hovered and a hover text is displayed:
image

I don’t know much about JS, so I have made only minimal changes. I have commented out the unnecessary parts of JS instead of removing them, for testing.

  • JS of codeblock widget introduces no button content, it is introduced through CSS pseudoelements, for easier editing without touching the widget definition.
  • I ended up using :clipboard: emoji as the button icon, it was easier to handle than SVG icons, and is less intrusive than a button with “Copy” text.

I think it looks and works reasonably now, but there is surely a lot of room for improvement. I’ll report here with any updates.

@vilc Note that adding a copy button to codeblocks is achievable with wikitext:

\widget $codeblock(code)
<$macrocall $name="copy-to-clipboard" src=<<code>>/>
<$genesis $type="$codeblock" $remappable="no" code=<<code>>/>
\end

This can be tagged as a global and the appearance customized using CSS.

4 Likes

@saqimtiaz this simplifies things a lot, thanks!


I tried it, and it seems to be more convenient, except that the language type icon of the code block cannot be configured, but in addition, the copy-to-clipboard text seems to be unhideable. Is there any way to hide it? Consider that not all situations require text, an icon is enough.

\widget $codeblock(code)
<div class="group">
<div class="absolute right-4 opacity-0 group-hover:opacity-100">
<$macrocall $name="copy-to-clipboard" src=<<code>>/>
</div>
<$genesis $type="$codeblock" $remappable="no" code=<<code>> class=""/>
</div>
\end
1 Like

Something along these lines should do the trick:

\widget $codeblock(code, language)
<$button message="tm-copy-to-clipboard" param=<<code>> tooltip="copy">
{{$:/core/images/copy-clipboard}}
</$button>
<$genesis $type="$codeblock" $remappable="no" code=<<code>> language=<<language>>/>
\end
2 Likes
\widget $codeblock(code)
<div class="group relative">
<div class="absolute right-0 opacity-0 group-hover:opacity-100">
<$button message="tm-copy-to-clipboard" param=<<code>> tooltip="copy">
{{$:/core/images/copy-clipboard}}
</$button>
</div>
<$genesis $type="$codeblock" $remappable="no" code=<<code>> language=<<language>>/>
</div>
\end

This is a quick implementation of tailwindcss, everything works perfectly except the code type language highlighting is not working properly yet @saqimtiaz

\widget $codeblock(code, language)
<div class="group relative">
<div class="absolute right-0 opacity-0 group-hover:opacity-100">
<$button message="tm-copy-to-clipboard" param=<<code>> tooltip="copy">
{{$:/core/images/copy-clipboard}}
</$button>
</div>
<$genesis $type="$codeblock" $remappable="no" code=<<code>> language=<<language>>/>
</div>
\end
4 Likes

Here’s a version independent of tailwind. I made the button invisible by default, greyed out when codeblock hovered greyed out by default, and more prominent when button hovered (using palette colors), similarly to how it looks here on discourse.
Also @oeyoews the inner div (with position: absolute) can be skipped I guess and its properties/classes assigned to the button itself, the $button widget supports class attribute.

Widget definition:

tags: $:/tags/Global

\widget $codeblock(code, language)
<div class="wilk-copy-code-button">
<$button message="tm-copy-to-clipboard" param=<<code>> tooltip="Copy" class="tc-btn-invisible">
{{$:/core/images/copy-clipboard}}
</$button>
<$genesis $type="$codeblock" $remappable="no" code=<<code>> language=<<language>>/>
</div>
\end

CSS:

tags: $:/tags/Stylesheet

div.wilk-copy-code-button {
	position: relative;
}
div.wilk-copy-code-button > button.tc-btn-invisible {
	position: absolute;
	right: 0;
	padding: 0.1em 0.2em;
	fill: <<colour tiddler-controls-foreground>>;
}
div.wilk-copy-code-button > button.tc-btn-invisible:hover {
	fill: <<colour tiddler-controls-foreground-hover>>;
}

Demo with drag-and-drop-ready tweak.

Edit: simplified the colors/hover behavior.

4 Likes

Just keep in mind that this is will be a usability issue on touch devices.

Edit: it looks like Discourse shows the button by default on touch devices.

Good point. I simplified it a bit and made it visible all the time, more prominent when button hovered. This is actually less distracting and flickery.

1 Like

Here’s my take on the copy code button (adapted from my old copy-code macro):

Same idea, but with an indication of the language used by the codeblock when there is enough space, and the ability to add a title with the full notation (I wonder if this could be possible with the short wikitext syntax, like for block quote…)

share

2 Likes

One little issue is when first line is long it overflows and covers the copy-button!

In TW 5.3.6 for a tiddler with code-body=yes, you will see two buttons.

1 Like

See this example

Thanks for noticing! I see it comes from this PR: Add Copy to Clipboard Button to Code Template by kookma · Pull Request #8430 · TiddlyWiki/TiddlyWiki5 · GitHub

I have quickly fixed it by making my button conditionally not displayed if the currentTiddler has code-body=yes, the newly introduced core button takes precedence. The widget code is now:

\widget $codeblock(code, language)
<div class="wilk-copy-code-button">
	<% if [<currentTiddler>!code-body[yes]] %>
		<$button
		message="tm-copy-to-clipboard"
		param=<<code>>
		tooltip="Copy"
		class="tc-btn-invisible">
			{{$:/core/images/copy-clipboard}}
		</$button>
	<% endif %>
	<$genesis $type="$codeblock" $remappable="no" code=<<code>> language=<<language>>/>
</div>
\end

My demo has been updated as well.

I would have liked it more to always show the custom button and never show the core button, but I don’t see a way of doing it without overriding the core view template or introducing a custom view template with the cascade.

1 Like

Thank you for the update. Please also note to the Cascades where some tiddlers are dynamically displayed as code.