Stack Apps is a question and answer site for apps, scripts, and development with the Stack Exchange API. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Screenshot / Code Snippet

enter image description here


This small UserScript makes it easier to copy the URL of the current question into pre-formatted Markdown. Once installed, it adds a 'copy' link to the question.


MIT License



Any browser that can install UserScripts.


I can be reached at


JavaScript + jQuery

share|improve this question
Would be cool...if it didn't use flash. ): – Rebecca Chernoff Feb 28 '11 at 21:52
@Rebecca: Don't worry... a Flash-free version is in the works! – Nathan Osman Feb 28 '11 at 21:56
@Rebecca: ...and done! No more flash :) The download link is the same. – Nathan Osman Feb 28 '11 at 22:22
Nice job. Thanks! – Klaus Byskov Hoffmann Mar 1 '11 at 0:07
When I copy the link to an answer, the box appears near the first "copy" link (the one under the question). This behavior is pretty annoying. It should appear next to the "copy" link that triggered displaying the box. – Klaus Byskov Hoffmann Mar 1 '11 at 19:29
@Klaus: Wow - it wasn't even designed to display a copy link next to answers in the first place. I'll try to get that fixed soon. – Nathan Osman Mar 1 '11 at 19:34
Cool, thanks :-) – Klaus Byskov Hoffmann Mar 1 '11 at 19:37
+1 sweet! This is a good workaround for the issue I raise here.… thanks for this! – Pekka 웃 Apr 30 '11 at 15:58
The script doesn't seem to work on all SE sites, notably on MSU -- maybe you could update it? – slhck Mar 4 '12 at 12:53
@slhck: Updated and fixed. – Nathan Osman Mar 4 '12 at 20:46
Ideally, this should copy the personalised (and shorter!) link instead of the full canonical link. – Konrad Rudolph May 16 '12 at 16:18
Copying the link for closed questions inserts [closed] into the Markdown link title, which isn't valid. Ideally, it should be simply stripped . – slhck Sep 10 '12 at 17:26
The link is down, could you update it? – slhck Apr 15 '14 at 19:39
I created a script that changes the very share link shown in the dialog: Convert share links to markdown [title](url) – brasofilo Sep 29 '14 at 14:54
@slhck: I've restored the original file. – Nathan Osman Dec 24 '14 at 19:14

Thank you for this script. It was basically the thing I was looking for when I asked for a Second 'link' button below posts which provides a comment style link in the form [post title](http://posturl).

There are however some things not yet perfect. For once I also like to have such links to answers not just to question. In this case the question title is still used but the URL of the answer should be used. At the moment every post (Qs and As) get the 'copy' link (all with the same id, which is invalid HTML), but the pop-up window only appears beside the question.

Also, the short URL should be used to allow for more additional text in comments.

I took the liberty to add these features to your code. Feel free to take over and adapt any changes. I added (modified) to the @name and renamed it to copy2.user.js to allow both versions to be installed at the same time (with one usually disabled).

Code preview:

Installation link:

// ==UserScript==
// @name          Copy Question Link Markdown (modified)
// @author        Nathan Osman
// @author        Martin Scharrer
// @namespace
// @description   Adds a button for copying the markdown of a post's URL to the clipboard
// @include*
// @include*
// @include*
// @include*
// @include*
// @include*
// @include*
// @include*
// @include       http://**
// ==/UserScript==

/* Modified by Martin Scharrer 14th April 2012 to support links to answers and to use short form URLs.
 * Changelog:
 *  o Added support for answer posts.
 *    - The pop-up window now appears beside the clicked 'copy' button, not at the very first one.
 *    - The included URL will point to the post the button belongs to, not always to the question.
 *  o The short version of the URL is now used to minimize the number of characters.
 *  o Changed "id='copy-button'" to "class='copy-button'" to allow multiple buttons.
 *    Before all posts got the button, which incorrectly had all the same id.
 *  o The object of the 'copy' button is now passed along with the click, not determined by its id.
 * */

// Here I borrow a couple functions I wrote for another
// UserScript that makes it easy to provide functions
// with complete access to the page.
function EmbedFunctionOnPageAndExecute(function_contents)
    var exec_script = document.createElement('script');
    exec_script.type = 'text/javascript';
    exec_script.textContent = "(" + function_contents.toString() + ")()";

// ...the other one
function EmbedFunctionOnPage(function_name, function_contents)
    var exec_script = document.createElement('script');
    exec_script.type = 'text/javascript';
    exec_script.textContent = function_contents.toString().replace(/function ?/, 'function ' + function_name);

// The code to execute when the ZeroClipboard lib loads
EmbedFunctionOnPage('DoCopy', function(button) {
    // Get ids required to build short URL to the post
    var questionid = location.path.match(/\/questions\/(\d+)\/.*/)[1];
    var shortquestionpath = $("#link-post-" + questionid).attr("href");
    var userid = shortquestionpath.substr( questionid.length + 4 ); // "/q/<questionid>/<userid>"
    var answerid = $(button).parents("div.answer").log("answer").attr("data-answerid");
    var shorturl;
    if (answerid) {
        shorturl = "http://" + + "/a/" + answerid + "/" + userid;
    else {
        shorturl = "http://" + + shortquestionpath;

    // Determine the content of the DIV
    var content = '<b>Copy the following:</b><br /><br /><textarea id="copy-content" style="width: 440px; height: 80px;">[' +
                  $('#question-header .question-hyperlink').text() + '](' + shorturl + ')</textarea>';

    $('body').append('<div id="copy-popup" class="popup" style="width: 450px; position: absolute; display: none;">' +
                     '<div class="popup-close"><a title="close this popup">×</a></div>' + content + '</div>');

    // Assign the close action to the 'x'
    $('#copy-popup .popup-close').click(function() { $('#copy-popup').fadeOut(300, function() { $('#copy-popup').remove(); }); });

    // Position the dialog
    var pos    = $(button).position();
    var height = $(button).height();

    $('#copy-popup').css('left', pos.left);
    $('#copy-popup').css('top', + height + 3);

    $('#copy-popup').fadeIn(500, function() {

        // Select the contents
        var textarea = document.getElementById('copy-content');




// The code that gets executed right away.
EmbedFunctionOnPageAndExecute(function() {

    jQuery.fn.log = function (msg) {
    console.log("%s: %o", msg, this);
    return this;
    // Embed the copy item
    $('.post-menu').append("<span class='lsep'>|</span><a href='javascript:void(0)' onclick='DoCopy(this)' class='copy-button'>copy</a>");

share|improve this answer

This script is now unnecessary in questions and answers, where raw links are replaced by the current question title. However, this feature is [status-declined] for comments and doesn't work in Chat, which also uses mini-markdown. Chat does have oneboxing, but you can't insert names inline without this script or a bunch of typing or copy-pasting.

If my terrible JavaScript skills are correct, you're currently using location.href to determine the page. This text is something like:

That's 96 characters, a fairly long URL (but not maximally long, that's over 120 characters!). Unfortunately, the places where this script is necessary and useful (chat and comments) both have character limits.

Please change this to use the shorter and format. That seems like it would be a trivial Javascript string manipulation. Here's an attempt, I make no assumptions as to its validity, speed, or idiomatic-ness:

function minify(url) {

    var question_re = /(^\D+)question\/(\d+)/;

    var answer_re = /\/\d+#\d+$/;
    if (re.test(answer_re)) {
       return url.replace(question_re, '$1q$2') .. url.replace(answer_re);
    } else {
       return url.replace(qestion_re, '$1q$2');

and a testcase.

function AssertException(message) { this.message = message; }
AssertException.prototype.toString = function () {
  return 'AssertException: ' + this.message;

function assert_equal(expression, result) {
  if (expression != result) {
    throw new AssertException('Expression produced "' .. expression .. '" which did not equal "' .. result .. '".');

 // Test function:
function verify_minify()


    // Standard Trilogy question
    //With answer ID:
    //With Meta prefix:
    //With Meta prefix and answer ID:
    //With site.stackexchange format: 
    //With site.stackexchange format and answer ID: 
    //With site.stackexchange format, meta prefix, and answer ID: 

    alert('Tests passed.');


Note: I didn't actually run any of these except to verify that the syntax highlighter in my text editor didn't break, I don't have any kind of a development environment set up and don't know how to do that.

share|improve this answer
I'll see what I can do - I didn't realize there was still a need for this script. – Nathan Osman Oct 26 '11 at 17:32

You must log in to answer this question.

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