Docfx: Feature Request: Code Copy Link

Created on 16 Sep 2019  路  3Comments  路  Source: dotnet/docfx

Hi,

when writing pages with markdown, code snippets can be inserted.

On Microsoft pages, e.g., https://docs.microsoft.com/en-us/dotnet/api/system.string?view=netframework-4.8
there is a Link to copy the code to clipboard, which is really helpful.

I would suggest to add such a button (optionally) to autogenerated pages by docfx

Area-Template feature-request help-wanted

Most helpful comment

I've created an implementation that models what happens on docs.microsoft.com that works within the docfx code blocks:

.code-header {
  box-sizing: content-box;
  background-color: #f2f2f2;
  color: #171717;
  display: flex;
  flex-direction: row;
  border: 1px solid #e3e3e3;
  border-bottom: 0;
  margin-top: 16px;
  min-height: 30px;
}

.tabGroup section[role="tabpanel"] .code-header {
  margin-left: -16px;
  margin-right: -16px;
}

.tabGroup section[role="tabpanel"] .code-header:first-child {
  margin-top: -16px;
}

.code-header > .language {
  padding: 2px 16px;
  flex-grow: 1;
  text-transform: uppercase;
  line-height: 26px;
}

.code-header > .action {
  position: relative;
  padding: 2px 10px;
  background-color: transparent;
  border: 0 solid #e3e3e3;
  border-left-width: 1px;
  color: #171717;
  cursor: pointer;
  display: flex;
  align-items: center;
  line-height: normal;
}

.code-header .glyphicon {
  margin-right: 0.25em;
}

.code-header > .action:hover {
  background-color: #fafafa;
}

.code-header + pre {
  margin-top: 0;
  border: 1px solid #e3e3e3;
}

.code-header > .action .successful-copy-alert {
  justify-content: center;
  align-items: center;
  right: 0;
  left: 0;
  bottom: 0;
  top: 0;
  position: absolute;
  display: flex;
  background-color: #128712;
  outline-color: #fff;
  color: #fff;
}

.code-header > .action .successful-copy-alert.is-transparent {
  opacity: 0;
  transition: 500ms opacity ease-in-out;
}
$(function() {
    var copyToClipboard = function(text) {
        // Create a textblock and assign the text and add to document
        var el = document.createElement('textarea');
        el.value = text;
        document.body.appendChild(el);
        el.style.display = "block";

        // select the entire textblock
        if (window.document.documentMode)
            el.setSelectionRange(0, el.value.length);
        else
            el.select();

        // copy to clipboard
        document.execCommand('copy');

        // clean up element
        document.body.removeChild(el);
    }

    $("code.hljs").each(function() {
        var $this = $(this);
        var language = /lang-(.+?)(\s|$)/.exec($this.attr("class"))[1].toUpperCase();
        if (language === 'CS') {
            language = "C#";
        }
        if (language === 'JS') {
            language = "JavaScript";
        }
        var $codeHeader = $(
            '<div class="code-header">'+
            '    <span class="language">'+ language +'</span>'+
            '    <button type="button" class="action" aria-label="Copy code">'+
            '       <span class="icon"><span class="glyphicon glyphicon-duplicate" role="presentation"></span></span>'+
            '       <span>Copy</span>'+
            '       <div class="successful-copy-alert is-transparent" aria-hidden="true">'+
            '           <span class="icon is-size-large">'+
            '               <span class="glyphicon glyphicon-ok" role="presentation"></span>'+
            '           </span>'+
            '       </div>'+
            '   </button>'+
            '</div>'
        );
        $this.closest("pre").before($codeHeader);
        $codeHeader.find("button").click(function() {
            copyToClipboard($this.closest("pre").text());
            var successAlert = $(this).find(".successful-copy-alert");
            successAlert.removeClass("is-transparent");
            setTimeout(function() {successAlert.addClass("is-transparent");}, 2000);
        });
    });
});

Here's what it looks like on the documentation site I'm building (not deployed yet, running locally for now):

image
image

All 3 comments

What about this feature?

+1 this would be awesome (in addition to the fact it shows the language of the code in the header of the block). I've done a bunch of Googling, but couldn't find any reference to an open source plugin that docs.microsoft.com was using and tried to look through the various git repos for docs.microsoft.com but got lost pretty quick.

I've created an implementation that models what happens on docs.microsoft.com that works within the docfx code blocks:

.code-header {
  box-sizing: content-box;
  background-color: #f2f2f2;
  color: #171717;
  display: flex;
  flex-direction: row;
  border: 1px solid #e3e3e3;
  border-bottom: 0;
  margin-top: 16px;
  min-height: 30px;
}

.tabGroup section[role="tabpanel"] .code-header {
  margin-left: -16px;
  margin-right: -16px;
}

.tabGroup section[role="tabpanel"] .code-header:first-child {
  margin-top: -16px;
}

.code-header > .language {
  padding: 2px 16px;
  flex-grow: 1;
  text-transform: uppercase;
  line-height: 26px;
}

.code-header > .action {
  position: relative;
  padding: 2px 10px;
  background-color: transparent;
  border: 0 solid #e3e3e3;
  border-left-width: 1px;
  color: #171717;
  cursor: pointer;
  display: flex;
  align-items: center;
  line-height: normal;
}

.code-header .glyphicon {
  margin-right: 0.25em;
}

.code-header > .action:hover {
  background-color: #fafafa;
}

.code-header + pre {
  margin-top: 0;
  border: 1px solid #e3e3e3;
}

.code-header > .action .successful-copy-alert {
  justify-content: center;
  align-items: center;
  right: 0;
  left: 0;
  bottom: 0;
  top: 0;
  position: absolute;
  display: flex;
  background-color: #128712;
  outline-color: #fff;
  color: #fff;
}

.code-header > .action .successful-copy-alert.is-transparent {
  opacity: 0;
  transition: 500ms opacity ease-in-out;
}
$(function() {
    var copyToClipboard = function(text) {
        // Create a textblock and assign the text and add to document
        var el = document.createElement('textarea');
        el.value = text;
        document.body.appendChild(el);
        el.style.display = "block";

        // select the entire textblock
        if (window.document.documentMode)
            el.setSelectionRange(0, el.value.length);
        else
            el.select();

        // copy to clipboard
        document.execCommand('copy');

        // clean up element
        document.body.removeChild(el);
    }

    $("code.hljs").each(function() {
        var $this = $(this);
        var language = /lang-(.+?)(\s|$)/.exec($this.attr("class"))[1].toUpperCase();
        if (language === 'CS') {
            language = "C#";
        }
        if (language === 'JS') {
            language = "JavaScript";
        }
        var $codeHeader = $(
            '<div class="code-header">'+
            '    <span class="language">'+ language +'</span>'+
            '    <button type="button" class="action" aria-label="Copy code">'+
            '       <span class="icon"><span class="glyphicon glyphicon-duplicate" role="presentation"></span></span>'+
            '       <span>Copy</span>'+
            '       <div class="successful-copy-alert is-transparent" aria-hidden="true">'+
            '           <span class="icon is-size-large">'+
            '               <span class="glyphicon glyphicon-ok" role="presentation"></span>'+
            '           </span>'+
            '       </div>'+
            '   </button>'+
            '</div>'
        );
        $this.closest("pre").before($codeHeader);
        $codeHeader.find("button").click(function() {
            copyToClipboard($this.closest("pre").text());
            var successAlert = $(this).find(".successful-copy-alert");
            successAlert.removeClass("is-transparent");
            setTimeout(function() {successAlert.addClass("is-transparent");}, 2000);
        });
    });
});

Here's what it looks like on the documentation site I'm building (not deployed yet, running locally for now):

image
image

Was this page helpful?
0 / 5 - 0 ratings