42

In an answer, I was adding some links to the documentation, after I wrote some PHP code. As result, the code was altered.

Take as example the following Markdown with an indented code block.

    if (isset($item['load_functions'][1]) && !empty($item['map'][1]) && $item['load_functions'][1] == 'node_load') {
      $node = $router_item['map'][1];
    }
    else {
      // The menu item is not for a node.
    }

After I add the first link (in a regular paragraph), I get the following, as expected.

    if (isset($item['load_functions'][1]) && !empty($item['map'][1]) && $item['load_functions'][1] == 'node_load') {
      $node = $router_item['map'][1];
    }
    else {
      // The menu item is not for a node.
    }

See [menu_get_object()][1]

[1]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_object/7

After I add the second link, I get the following, where the [1] indexes in the code block have been interpreted as links.

    if (isset($item['load_functions'][1]) && !empty($item['map'][2]) && $item['load_functions'][3] == 'node_load') {
      $node = $router_item['map'][4];
    }
    else {
      // The menu item is not for a node.
    }

See [menu_get_object()][5]

And see [menu_get_item()][6]

[1]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_object/7
[2]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_object/7
[3]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_object/7
[4]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_object/7
[5]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_object/7
[6]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_item/7

Notice that the code is correctly indented with 4 spaces.

I was able to reproduce the bug in the sandbox. I also tried with another browser, as I noticed I was using a not supported browser (Firefox 19.0a1). With Safari 6.0.2, the result is the same.

The issues are two:

  • Perfectly valid code is rewritten.
  • Markdown links pointing to the same URL are rewritten. Even in the case I didn't write PHP code, but Markdown markup, there isn't any need to re-write all the links.

Suppose I have the following markdown.

[Example link][1]

[Same example link][1]

[The same link once again][1]

[1]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_item/7

If I add another link, the other links should not be changed. This is what instead happens.

[Example link][1]

[Same example link][2]

[The same link once again][3]

[Another link][4]

[1]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_item/7
[2]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_item/7
[3]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_item/7
[4]: http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_object/7

See the sandbox example.

3

2 Answers 2

15

First of, I have not changed anything about the link duplication since that is not really a big problem. I may look at it at some point, but I don't promise anything. I eventually also fixed the link duplication.

The really big problem though, where code is changed when it contains something that looks like it could be a reference link, will be fixed in the next build.

For the curious:

The problem is that you don't know what's really a link reference and what just looks like one until you actually run the whole post through the Markdown converter. So… that's what happens now.

Imagine you have this Markdown:

My [code][1]:

    foo[7][1] = *p;

Why doesn't it work?

  [1]: https://github.com/my/repo

When you now add a new link via Ctrl-L, we first modify anything that looks like it could be a reference, and give it a URL like it is one. It will look like this:

My [code][3]:

    foo[7][22] = *p;

Why doesn't it work?


 [3]: http://this-is-a-real-link.biz/3/unicorn
 [22]: http://this-is-a-real-link.biz/22/unicorn

We convert this to HTML, getting this:

<p>My <a href="http://this-is-a-real-link.biz/3/unicorn">code</a>:</p>

<pre><code>foo[7][22] = *p;
</code></pre>

<p>Why doesn't it work?</p>

Note how only one of the two URLs appears in the HTML, because the [22] non-reference is in code.

After this preparation, we now go back to your original Markdown and do the renumbering dance like it has always happened, but now we skip those matches that were not turned into URLs above.

How do we know what (potential) reference corresponds to what URL? We know it because the number we choose both for the reference and in the URL, 3 and 22 in our example, are the character position of the match in the original Markdown source.

So when we find the match in foo[7][1] = *p;, this match begins (with the initial open bracket) at character position 22. We then check if we find http://this-is-a-real-link.biz/22/unicorn in the converted rewritten version, which we don't. So we know this match doesn't represent an actual reference, and we leave it alone.

If you're even more curious, the code is here: https://code.google.com/p/pagedown/source/detail?r=84795e74c78df1ee83ce54d31f0f2563fc3542c1 (yes, I know I have to get this out of Google Code).

7

I had the same problem and whilst investigating this, Tim Stone kindly pointed me to this Question in the tavern (starting here).

He explained this "is an existing bug" and "the problem is mostly that the editor piece is (mostly) unaware of the parser behaviour, so it doesn't have the context to make smart decisions most of the time."
He would also look into "how difficult it would be to submit a patch to PageDown to fix it here shortly" (yippie)!

Current workaround:
Don't use the editor's hyperlink function (both button and keyboard shortcut ctrl+L).
Instead, add the links manually:

  • [text](url)
  • <a href="url">text</a>
  • or url-list: [text][url_number]
    with accompanying
      [url_number]: url
    (at the bottom of the answer)

Hope this helps for now!

Kitten draws red freehand-circle around important things in life

1
  • 2
    In my case, the four spaces at the beginning of the text could be taken as meaning "this text is code that doesn't need to be touched." That is why we indent the code with four spaces: to let the parser know it's text it doesn't need to parse. Then, it is not necessary to pass from one link to four links as in the last case. The editor is just JavaScript code that doesn't need to rewrite existing links, which is not something the Markdown parser would do.
    – apaderno
    Apr 11, 2014 at 16:37

You must log in to answer this question.

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