google / docsy

A set of Hugo doc templates for launching open source content.
https://docsy.dev
Apache License 2.0
2.51k stars 877 forks source link

Copy only necessary items from the code block #818

Open iamrajiv opened 2 years ago

iamrajiv commented 2 years ago

Description

When I use the copy button to copy the codes then unnecessary characters are also copied like I want to copy the below code but do not want the $ character to be copied. I want to copy only echo "Hello World" after clicking the copy button.

$ echo "Hello World"
chalin commented 2 years ago

This is only when Prism is used, correct?

I've been able to fix this in other projects by adding user-select: none to the prompt class(es). Might you be willing to give that a try?

iamrajiv commented 2 years ago

Yeah sure @chalin. Can you send me the link to the project where you have fixed this issue? also, what does prompt class(es) mean?

chalin commented 2 years ago

This was fixed in the Flutter website. For example, see the code blocks on this page: https://docs.flutter.dev/get-started/install/macos#get-sdk

what does prompt class(es) mean?

I mean the CSS classes uses to style prompts in code blocks, such as the gp class in the case of the Flutter pages:

<span class="gp">$</span>
chalin commented 2 years ago

For the record, the folks at Stripe use CSS :before to insert prompts. For example, see https://stripe.com/docs/api/authentication:

image

That probably works best when there's a single command though.

at055612 commented 2 years ago

Prism has a command-line plugin https://prismjs.com/plugins/command-line/ that adds a prompt for you which is not user selectable. You just need to build a new pair of prism.{css,js} files with the command-line plugin added in, as described here

I have made my own shortcode for it like so

<!-- 
{{/*
Short code to add command line input/output
Usage:
command-line username hostname language
username - The username to appear in the prompt, defaults to 'user'
hostname - The hostname to appear in the prompt, defaults to 'localhost'
language - The language of the content, defaults to bash

Prefix lines with '(out)' and it will render them as output lines

See https://prismjs.com/plugins/command-line/

e.g.:
{{% command-line "jdoe" "bigserver" %}}
echo "hello world"
(out) class
id
(out) uid=1000(jdoe) gid=1000(jdoe)
{{% /command-line %}}

*/}}
-->

{{ $user := .Get 0 | default "user" }}
{{ $host := .Get 1 | default "localhost" }}
{{ $language := .Get 2 | default "bash" }}

<div class="code-toolbar">
  <pre class="command-line language-{{ $language }}" data-user="{{ $user }}" data-host="{{ $host }}" data-filter-output="(out)">
  {{- with (.Inner | default "" ) -}}
    <code>{{- trim ( . | default "" ) "\n" -}}</code>
  {{- end -}}
  </pre>
</div>

e.g. in your markdown content

{{< command-line "david" "wopr" >}}
echo "hello world"
(out)hello world
id
(out)uid=1000(david) gid=1000(david)
{{</ command-line >}}

I have added this CSS to stop the output lines being selectable and to tweak the look a bit.

// Font size is too big in the code blocks
pre[class*=language-] {
  font-size: small !important;
}

code[class*=language-] > span:not(.command-line-prompt) {
  user-select: initial;
}

// Shell output lines
.command-line code[class*=language-]:not(span) {
  // Stop them being selectable so the user can just copy the commands
  user-select: none;

  // Make the output lines distinct from the commands
  color: #999;
}

On my site it looks like this when I select with the mouse:

image

The prism copy plugin does not seem to work with the command line plugin on my site but this jsfiddle shows they can work together https://jsfiddle.net/cfjhrkxz/. I need to figure out why they are conflicting for me. Also now the content is inside a shortcode rather than a fenced block I lose the syntax highlighting when editing it in vim but that's my problem not the user's.

UPDATE I was wrong. Preventing user selection and changing the colour of the shell output does not work as there is no way to distinguish the input from the output text unless the input text is all highlighted in some way (as it was in this example). It would need a change to the plugin to surround the output text with something like <span class="command-line-output"> so you can make the distinction. If you don't need to show shell output then this plugin may work for you.

rothgar commented 1 year ago

docusaurus does this automatically and it's really handy. It also lets you have 1 block with multiple commands to select. Here's an example

image from this page https://www.eksworkshop.com/docs/observability/open-source-metrics/amp-ws

It uses the code block from here https://github.com/aws-samples/eks-workshop-v2/blob/main/website/docs/observability/open-source-metrics/amp-ws.md

It'd be great to have this supported in docsy too :+1: