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.

  • You can copy comments source with the iOS app – Cai Oct 24 '16 at 7:53
  • 1
    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
9

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.

  • Good effort Cai! – Patrick Hofman 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" :/ – DavidPostill 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 – DavidPostill 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 ... :) – DavidPostill 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
  • Thanks. It's now working. I did a browser restart a while ago so maybe that fixed it. – DavidPostill Oct 26 '16 at 11:48
  • Was working before update. Updated anyway :) – DavidPostill 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. – DavidPostill Oct 26 '16 at 12:12
  • Still no link. Or error message. Now I'm stumped :/ – DavidPostill Oct 26 '16 at 12:20
  • 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
6

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
    Thanks, but I'd call this a workaround and not a solution. – Federico Poloni 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.

  • 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. – Federico Poloni Oct 24 '16 at 8:14
  • 1
    The same can be said about moderators who have to clean up all those converted answers. – Patrick Hofman 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. – Federico Poloni 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();
        }
    }
});
  • 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 .