6

I wrote a comment, and OP asked me to convert it to an answer and expand on it. I cannot simply copy-and-paste it because there is some nontrivial Markdown and Mathjax code in it. I cannot access its source because the 5-minute editing window is expired. Currently my only option is retyping everything, which is tedious work.

Related questions (but not duplicates in my opinion, because the solutions suggested there are not appropriate in my use case): Add a "convert-comment-to-answer" button, Way to convert a comment to an answer?, Can we allow moderators to upgrade a comment to an answer?, Ability to convert an answer to a comment and comment to an answer.

2
  • You can copy comments source with the iOS app
    – Cai
    Oct 24 '16 at 7:53
  • 2
    I will add that there was a discussion about this on Meta MathOverflow: How to cut and paste. (I am mentioning this mainly because it is one of the sites you frequent. But most likely you've noticed that discussion on the local meta.) A post on this meta which might be useful: Is there a way to view a comment's source?
    – Martin
    Apr 29 '18 at 12:57
10

I don't like Mondays so to avoid doing a bit of serious work I wrote this little user script.

// ==UserScript==
// @name           Show Comment Markdown
// @namespace      cai
// @version        0.2
// @description    Show the Markdown source of a comment, useful for copy/pasting.
// @author         Cai
// @include        https://stackoverflow.com/*
// @include        https://serverfault.com/*
// @include        https://superuser.com/*
// @include        https://meta.stackoverflow.com/*
// @include        https://meta.serverfault.com/*
// @include        https://meta.superuser.com/*
// @include        https://stackapps.com/*
// @include        https://*.stackexchange.com/*
// @include        https://askubuntu.com/*
// @include        https://meta.askubuntu.com/*
// @include        https://mathoverflow.net/*
// @include        https://area51.stackexchange.com/proposals/*
// @exclude        https://chat.*/*
// @grant          none
// ==/UserScript==

function with_jquery(f) {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.textContent = "(" + f.toString() + ")(jQuery)";
    document.body.appendChild(script);
}

with_jquery(function ($) {

    $('head').append(
        $(
            '<style>' +
            '#markdown-clipboard { \
                 position: fixed; \
                 top: 0; left: 0; right: 0; bottom: 0; \
                 background: rgba(0,0,0,0.2); \
            } \
            #markdown-clipboard textarea { \
                 display: block; \
                 width: 400px; \
                 height: 160px; \
                 margin: auto; \
                 padding: 20px; \
                 box-shadow: 0 2px 5px rgba(12,13,14,0.3); \
                 background-color: #FFF; \
                 border: solid 1px #9fa6ad; \
            } \
            #markdown-clipboard-close { \
                 cursor: pointer; \
                 display: block; \
                 margin: 30vh auto 20px auto; \
                 text-align: center; \
                 font-size: 2em; \
                 color: #fff; \
                 background: #0C0D0E; \
                 width: 30px; \
                 height: 30px; \
                 line-height: 28px; \
            } \
            .show-markdown-link { \
                 cursor: pointer; \
                 color: #9199a1; \
                 opacity: 0; \
            } \
            .comment:hover .show-markdown-link { \
                 opacity: 1; \
            }' +
            '</style>'
        )
    );
    $('body').append('<div id="markdown-clipboard" style="display:none;"><span id="markdown-clipboard-close">&times;</span><textarea></textarea></div>');

    $(document).ajaxComplete(function(){
        $('.comments').each(make_copy_links);
    });

    $('.comments').each(make_copy_links);

    function make_copy_links() {
        $(this).find('.comment:not(:has(.show-markdown-link)) .comment-body').each(function () {
            $('<span class="show-markdown-link" title="Source">| Source</span>').click(show_markdown).appendTo(this);
        });
    }

    function show_markdown() {
        var comment = $(this).closest(".comment");
        var cid = comment.attr("id");
        var cdash = cid.lastIndexOf('-');
        var comment_id = cid.substring(cdash + 1);
        $.getJSON(window.location.protocol + '//api.stackexchange.com/2.2/comments/' + comment_id + '?site=' + window.location.hostname + '&filter=!)Q29lpdRHRpfMsqok1CFj-3(',
            function (data) {
                var markdown = data.items[0].body_markdown;
                $('#markdown-clipboard').show().find('textarea').html(markdown);
            }
        );
    }

    $('#markdown-clipboard-close').click(clear_clipboard);

    function clear_clipboard() {
        $('#markdown-clipboard').hide().find('textarea').html();
    }

});

This gives you a "Source" link at the end of every comment, which when clicked will show you the Markdown source of the comment in a popup.

Comment Markdown source popup

Limited testing on Chrome (54.0.2840.71) with Tampermonkey and Firefox (49.0.2) with Greasemonkey but it seems to work ok.

18
  • Good effort Cai! Oct 24 '16 at 13:01
  • I needed something to take my mind off the fact that it was Monday!
    – Cai
    Oct 24 '16 at 13:04
  • @Cai "NetworkError: 400 Bad Request - api.stackexchange.com/2.2/comments/…x-JSjjnMufvIgU.&_=1477404371402" :/ Oct 25 '16 at 14:07
  • @DavidPostill What's the last parameter there (&_=1477404371402)? It's not in my userscript. The url returns the comment fine for me regardless (see here)
    – Cai
    Oct 25 '16 at 14:18
  • @cai No idea. It's what is at the end of the error message returned when I click on "Source". There is no popup displayed. Windows 7 Home Premium 64 bit, Firefox 49.0.2 Oct 25 '16 at 16:58
  • @DavidPostill Ah ok, I only did some limited testing on OSX, I'll have a look at it later on see if I can figure out what's going on.
    – Cai
    Oct 25 '16 at 17:04
  • @Cai Thanks. It will be a useful script ... :) Oct 25 '16 at 17:05
  • Well I found out what the underscore parameter is (it's cache control)... That shouldn't affect anything though so not sure why you're getting the bad request (I just tested on Win 7 and all is working ok here) @DavidPostill
    – Cai
    Oct 26 '16 at 11:31
  • Just made an update though if you want to check if you're still getting the bad request (could you possibly have a look in firebugs console and see what errors it's showing if you are?)
    – Cai
    Oct 26 '16 at 11:32
  • 1
    Thanks. It's now working. I did a browser restart a while ago so maybe that fixed it. Oct 26 '16 at 11:48
  • Was working before update. Updated anyway :) Oct 26 '16 at 11:51
  • Glad you got it working :) the update mainly just hides the link unless you hover over the comment (the link was getting annoying) and doesn't exclude specific error messages if something does go wrong with the api request
    – Cai
    Oct 26 '16 at 11:54
  • Oooer. The update broke it. Now I don't get the link. Reverting. Oct 26 '16 at 12:12
  • 1
    @Zanna I'll have another look at it when I've got some time later to see if I can figure out why it's not working
    – Cai
    Oct 16 '17 at 13:43
  • 1
    Great User Script! Exactly what I was looking for and I didn't even know I was looking for it. The first time I used it, I didn't know how to close the Popup/Overlay when I was done, so I had to reload the page . Eventually I found the [X] (close) button. But it's in a non intuitive location, so the 2nd time I used it, I still didn't know how to close the Popup/Overlay (forgot). Perhaps the close button could be moved to a better location, or it could be made to close with any click outside the popup. Jul 8 '18 at 4:56
7

You can use the API to grab the Markdown of a comment.

  1. Get the ID of the comment. For example, the ID of #comment12345_67890 is 12345.

  2. Open https://api.stackexchange.com/docs/comments-by-ids#order=desc&sort=creation&filter=!1zSk*x-JSjj*nMufvIgU.
    This has a custom filter to return ‘body’ and ‘body_markdown’.

  3. Set the site by clicking ‘[edit]’ next to the site name, and paste the ID into the ‘ids’ box.

  4. The Markdown source is returned as ‘body_markdown’.

If you just need the MathJax, you can get the source of the MathJax by right-clicking on the Math and selecting Show Math As → TeX Commands.

1
  • 1
    Thanks, but I'd call this a workaround and not a solution. Oct 24 '16 at 8:16
3

While I agree a copy button is useful in some cases, I think we should prevent making it a convert comment-to-answer button. That would imply that comments are good answers by definition, which they aren't. 

I think a feature like in the iOS app would be useful, which allows to copy a comment, including its markdown. The app currently supports that for both the comment owner as other users.

3
  • Making a task unnecessarily hard to perform because it may lead to people posting bad answers seems excessive to me. Don't make us users waste our time. We already have a method to discourage low-quality answers: downvotes. Oct 24 '16 at 8:14
  • 1
    The same can be said about moderators who have to clean up all those converted answers. Oct 24 '16 at 8:22
  • What if "convert comment to answer" was a moderator tool? Then we'd just flag the comment for conversion. Oct 17 '17 at 6:42
2

This is essentially the same script as @cai's, except it displays the markdown in the same way as if you would edit the comment:

show comment markdown on stackexchange

Tested on Chrome with Tampermonkey.

// ==UserScript==
// @name           Show Comment Markdown
// @namespace      cai
// @version        0.2b
// @description    Show the Markdown source of a comment, useful for copy/pasting.
// @author         Cai (edited by me)
// @include        https://stackoverflow.com/*
// @include        https://serverfault.com/*
// @include        https://superuser.com/*
// @include        https://meta.stackoverflow.com/*
// @include        https://meta.serverfault.com/*
// @include        https://meta.superuser.com/*
// @include        https://stackapps.com/*
// @include        https://*.stackexchange.com/*
// @include        https://askubuntu.com/*
// @include        https://meta.askubuntu.com/*
// @include        https://mathoverflow.net/*
// @include        https://area51.stackexchange.com/proposals/*
// @exclude        https://chat.*/*
// @grant          none
// ==/UserScript==

/*jshint multistr: true */

function with_jquery(f) {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.textContent = "(" + f.toString() + ")(jQuery)";
    document.body.appendChild(script);
}

with_jquery(function ($) {
    $('head').append(
        $(
            '<style>' +
            '.show-markdown-link { \
                 cursor: pointer; \
                 color: #9199a1; \
                 opacity: 0; \
            } \
            .comment .show-markdown-link { \
                 opacity: 1; \
            }' +
            '</style>'
        )
    );
    $(document).ajaxComplete(function(){
        $('.comments').each(make_copy_links);
    });
    $('.comments').each(make_copy_links);

    function make_copy_links() {
        $(this).find('.comment:not(:has(a.comment-edit)):not(:has(span.show-markdown-link)) .comment-body').each(function () {
            $('<span class="show-markdown-link" title="Source">| Source</span>').click(show_markdown).appendTo(this);
        });
    }

    function show_markdown() {
        var comment = $(this).closest(".comment");
        var chtmlid = comment.attr("id");
        var cdash = chtmlid.lastIndexOf('-');
        var comment_id = chtmlid.substring(cdash + 1);
        var markdown;
        var textarea;
        if(comment.has('form.SCCoS').length) {
            markdown = $('div#SCCoS-source-' + comment_id).html();
            $('#SCCoS-' + comment_id).show();
            comment.find('.comment-text').prop('class', comment.find('.comment-text').prop('class') + ' comment-form');
            comment.find('.comment-body').hide();
            textarea = comment.find('textarea.SCCoS');
            reset_textarea(textarea, markdown);
        } else {
            $.getJSON(window.location.protocol + '//api.stackexchange.com/2.2/comments/' + comment_id + '?site=' + window.location.hostname + '&filter=!)Q29lpdRHRpfMsqok1CFj-3(',
                function (data) {
                    markdown = data.items[0].body_markdown;
                    var comment_text = $('#comment-' + comment_id).find('.comment-text');
                    comment_text.prop('class', comment_text.prop('class') + ' comment-form');
                    comment_text.append('\
                        <form class="SCCoS dno" style="display:block" id="SCCoS-' + comment_id + '"> \
                             <div id="SCCoS-source-' + comment_id +'" class="dno">' + markdown + '</div> \
                             <table> \
                                 <tbody class="js-comment-form-layout"> \
                                     <tr> \
                                         <td> \
                                             <textarea name="comment" cols="68" rows="3" class="SCCoS"></textarea> \
                                         </td> \
                                         <td> \
                                             <input id="SCCoS-close-' + comment_id + '" tabindex="0" type="button" value="Close"> \
                                             <br> \
                                             <a class="SCCoS-closeall edit-comment-cancel" tabindex="0">close all</a> \
                                         </td> \
                                     </tr> \
                                 </tbody> \
                             </table> \
                         </form>'
                     ).find('.comment-body').hide();
                     textarea = comment_text.find('textarea');
                     init_textarea(textarea, markdown);
                     $('#SCCoS-close-' + comment_id).click(function() {
                         hide_markdown(comment_id);
                     });
                     $('.SCCoS-closeall').click(function() {
                         hide_markdown();
                     });
                }
            ).fail(function(jqXHR, textStatus, errorThrown) {
                alert('Request failed! ' + textStatus);
            });
        }
    }

    function init_textarea(JQtextarea, text) {
        JQtextarea.html(text).focus();
    }

    function reset_textarea(JQtextarea, text) {
        JQtextarea.css('height', '5em');
        JQtextarea.val(text).focus();
    }

    function hide_markdown(comment_id) {
        if(comment_id === undefined) {
            $('form.SCCoS').each(function () {
                var id = $(this).prop('id');
                if(id.startsWith('SCCoS-')) {
                    hide_markdown(id.replace('SCCoS-',''));
                }
            });
        } else {
            $('#SCCoS-' + comment_id).hide();
            var comment = $('#comment-' + comment_id);
            comment.find('.comment-text').prop('class', comment.find('.comment-text').prop('class').replace(' comment-form',''));
            comment.find('.comment-body').show();
        }
    }
});
1
  • For some reason this is now creating excessive white space when clicking "Source", unlike in the screenshot...
    – user278533
    Jun 10 '18 at 18:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .