Commit c61512d4e18a873df229ba2fddb28dfddc423009

Authored by Dmitriy Zaporozhets
2 parents 6e47fbf5 61748c99

Merge branch 'header-anchors' of github.com:cirosantilli/gitlab-elearn into ciro…

…santilli-header-anchors

Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>

Conflicts:
	CHANGELOG
@@ -14,6 +14,7 @@ v 6.6.0 @@ -14,6 +14,7 @@ v 6.6.0
14 - Fix block/remove UI for admin::users#show page 14 - Fix block/remove UI for admin::users#show page
15 - Show users' group membership on users' activity page 15 - Show users' group membership on users' activity page
16 - User pages are visible without login if user is authorized to a public project 16 - User pages are visible without login if user is authorized to a public project
  17 + - Markdown rendered headers have id derived from their name and link to their id
17 18
18 v 6.5.1 19 v 6.5.1
19 - Fix branch selectbox when create merge request from fork 20 - Fix branch selectbox when create merge request from fork
app/assets/images/icon-link.png 0 → 100644

1019 Bytes

app/assets/stylesheets/generic/files.scss
@@ -50,7 +50,6 @@ @@ -50,7 +50,6 @@
50 } 50 }
51 51
52 &.wiki { 52 &.wiki {
53 - padding: 20px;  
54 font-size: 14px; 53 font-size: 14px;
55 line-height: 1.6; 54 line-height: 1.6;
56 55
app/assets/stylesheets/generic/issue_box.scss
@@ -23,11 +23,12 @@ @@ -23,11 +23,12 @@
23 line-height: 28px; 23 line-height: 28px;
24 margin: 0; 24 margin: 0;
25 color: #444; 25 color: #444;
  26 + border-bottom: 1px solid #eee;
26 } 27 }
27 28
28 .context { 29 .context {
29 border: none; 30 border: none;
30 - border-top: 1px solid #eee; 31 + border-bottom: 1px solid #eee;
31 } 32 }
32 33
33 .description { 34 .description {
@@ -35,7 +36,7 @@ @@ -35,7 +36,7 @@
35 } 36 }
36 37
37 .title, .context, .description { 38 .title, .context, .description {
38 - padding: 15px; 39 + padding: 15px 15px 15px 30px;
39 40
40 .clearfix { 41 .clearfix {
41 margin: 0; 42 margin: 0;
app/assets/stylesheets/generic/typography.scss
@@ -90,6 +90,27 @@ a:focus { @@ -90,6 +90,27 @@ a:focus {
90 90
91 font-size: 14px; 91 font-size: 14px;
92 line-height: 1.6; 92 line-height: 1.6;
  93 +
  94 + /* Link to current header. */
  95 + h1, h2, h3, h4, h5, h6 {
  96 + position: relative;
  97 + &:hover > :last-child {
  98 + $size: 16px;
  99 + position: absolute;
  100 + right: 100%;
  101 + top: 50%;
  102 + margin-top: -$size/2;
  103 + margin-right: 0px;
  104 + padding-right: 20px;
  105 + display: inline-block;
  106 + width: $size;
  107 + height: $size;
  108 + background-image: url("icon-link.png");
  109 + background-size: contain;
  110 + background-repeat: no-repeat;
  111 + }
  112 + }
  113 +
93 ul { 114 ul {
94 padding: 0; 115 padding: 0;
95 margin: 0 0 9px 25px !important; 116 margin: 0 0 9px 25px !important;
app/assets/stylesheets/main/mixins.scss
@@ -114,6 +114,10 @@ @@ -114,6 +114,10 @@
114 font-size: 1.2em; 114 font-size: 1.2em;
115 } 115 }
116 116
  117 + // Larger 30px left margin is required for the header link icon.
  118 + // Use on all markdown including those without header links for uniformity.
  119 + margin: 20px 20px 20px 30px;
  120 +
117 blockquote p { 121 blockquote p {
118 color: #888; 122 color: #888;
119 font-size: 14px; 123 font-size: 14px;
app/helpers/gitlab_markdown_helper.rb
@@ -28,14 +28,16 @@ module GitlabMarkdownHelper @@ -28,14 +28,16 @@ module GitlabMarkdownHelper
28 link_to(gfm_body.html_safe, url, html_options) 28 link_to(gfm_body.html_safe, url, html_options)
29 end 29 end
30 30
31 - def markdown(text)  
32 - unless @markdown  
33 - gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self,  
34 - # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-  
35 - filter_html: true,  
36 - with_toc_data: true,  
37 - hard_wrap: true,  
38 - safe_links_only: true) 31 + def markdown(text, options={})
  32 + unless (@markdown and options == @options)
  33 + @options = options
  34 + gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self, {
  35 + # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-
  36 + filter_html: true,
  37 + with_toc_data: true,
  38 + hard_wrap: true,
  39 + safe_links_only: true
  40 + }.merge(options))
39 @markdown = Redcarpet::Markdown.new(gitlab_renderer, 41 @markdown = Redcarpet::Markdown.new(gitlab_renderer,
40 # see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use 42 # see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
41 no_intra_emphasis: true, 43 no_intra_emphasis: true,
@@ -47,7 +49,6 @@ module GitlabMarkdownHelper @@ -47,7 +49,6 @@ module GitlabMarkdownHelper
47 space_after_headers: true, 49 space_after_headers: true,
48 superscript: true) 50 superscript: true)
49 end 51 end
50 -  
51 @markdown.render(text).html_safe 52 @markdown.render(text).html_safe
52 end 53 end
53 54
app/views/help/_layout.html.haml
@@ -8,4 +8,5 @@ @@ -8,4 +8,5 @@
8 = link_to title, path 8 = link_to title, path
9 9
10 .col-md-9 10 .col-md-9
11 - = yield 11 + .wiki
  12 + = yield
app/views/projects/issues/show.html.haml
@@ -46,10 +46,9 @@ @@ -46,10 +46,9 @@
46 = render partial: 'issue_context', locals: { issue: @issue } 46 = render partial: 'issue_context', locals: { issue: @issue }
47 47
48 - if @issue.description.present? 48 - if @issue.description.present?
49 - .description  
50 - .wiki  
51 - = preserve do  
52 - = markdown @issue.description 49 + .wiki
  50 + = preserve do
  51 + = markdown @issue.description
53 52
54 - content_for :note_actions do 53 - content_for :note_actions do
55 - if can?(current_user, :modify_issue, @issue) 54 - if can?(current_user, :modify_issue, @issue)
app/views/projects/merge_requests/show/_mr_box.html.haml
@@ -15,10 +15,9 @@ @@ -15,10 +15,9 @@
15 15
16 16
17 - if @merge_request.description.present? 17 - if @merge_request.description.present?
18 - .description  
19 - .wiki  
20 - = preserve do  
21 - = markdown @merge_request.description 18 + .wiki
  19 + = preserve do
  20 + = markdown @merge_request.description
22 21
23 - if @merge_request.closed? 22 - if @merge_request.closed?
24 .description.alert-danger 23 .description.alert-danger
app/views/projects/milestones/show.html.haml
@@ -42,13 +42,11 @@ @@ -42,13 +42,11 @@
42 .progress.progress-info 42 .progress.progress-info
43 .progress-bar{style: "width: #{@milestone.percent_complete}%;"} 43 .progress-bar{style: "width: #{@milestone.percent_complete}%;"}
44 44
45 -  
46 - if @milestone.description.present? 45 - if @milestone.description.present?
47 - .description 46 + .wiki
48 = preserve do 47 = preserve do
49 = markdown @milestone.description 48 = markdown @milestone.description
50 49
51 -  
52 %ul.nav.nav-tabs.append-bottom-10 50 %ul.nav.nav-tabs.append-bottom-10
53 %li.active 51 %li.active
54 = link_to '#tab-issues', 'data-toggle' => 'tab' do 52 = link_to '#tab-issues', 'data-toggle' => 'tab' do
app/views/projects/notes/_note.html.haml
@@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
31 .note-body 31 .note-body
32 .note-text 32 .note-text
33 = preserve do 33 = preserve do
34 - = markdown(note.note) 34 + = markdown(note.note, {no_header_anchors: true})
35 35
36 .note-edit-form 36 .note-edit-form
37 = form_for note, url: project_note_path(@project, note), method: :put, remote: true, authenticity_token: true do |f| 37 = form_for note, url: project_note_path(@project, note), method: :put, remote: true, authenticity_token: true do |f|
doc/markdown/markdown.md
1 ---------------------------------------------- 1 ----------------------------------------------
2 2
3 -Table of Contents 3 +Table of Contents
4 ================= 4 =================
5 5
6 ---------------------------------------------- 6 ----------------------------------------------
7 7
8 -[GitLab Flavored Markdown](#toc_3)  
9 --------------------------------  
10 -[Newlines](#toc_4)  
11 -[Multiple underscores in words](#toc_5)  
12 -[URL autolinking](#toc_6)  
13 -[Code and Syntax Highlighting](#toc_7)  
14 -[Emoji](#toc_8)  
15 -[Special GitLab references](#toc_9)  
16 -  
17 -  
18 -  
19 -[Standard Markdown](#toc_10)  
20 -------------------------------  
21 -[Headers](#toc_11)  
22 -[Emphasis](#toc_20)  
23 -[Lists](#toc_21)  
24 -[Links](#toc_22)  
25 -[Images](#toc_23)  
26 -[Blockquotes](#toc_24)  
27 -[Inline HTML](#toc_25)  
28 -[Horizontal Rule](#toc_26)  
29 -[Line Breaks](#toc_27)  
30 -[Tables](#toc_28)  
31 -  
32 -[References](#toc_29)  
33 ---------------------- 8 +**[GitLab Flavored Markdown](#gitlab-flavored-markdown-gfm)**
  9 +
  10 +[Newlines](#newlines)
  11 +[Multiple underscores in words](#multiple-underscores-in-words)
  12 +[URL autolinking](#url-autolinking)
  13 +[Code and Syntax Highlighting](#code-and-syntax-highlighting)
  14 +[Emoji](#emoji)
  15 +[Special GitLab references](#special-gitlab-references)
  16 +
  17 +**[Standard Markdown](#standard-markdown)**
  18 +
  19 +[Headers](#headers)
  20 +[Emphasis](#emphasis)
  21 +[Lists](#lists)
  22 +[Links](#links)
  23 +[Images](#images)
  24 +[Blockquotes](#blockquotes)
  25 +[Inline HTML](#inline-html)
  26 +[Horizontal Rule](#horizontal-rule)
  27 +[Line Breaks](#line-breaks)
  28 +[Tables](#tables)
  29 +
  30 +**[References](#references)**
34 31
35 ---------------------------------------------- 32 ----------------------------------------------
36 33
37 -<a name="gfm" />  
38 -GitLab Flavored Markdown (GFM) 34 +GitLab Flavored Markdown (GFM)
39 ============================== 35 ==============================
40 For GitLab we developed something we call "GitLab Flavored Markdown" (GFM). It extends the standard Markdown in a few significant ways to add some useful functionality. 36 For GitLab we developed something we call "GitLab Flavored Markdown" (GFM). It extends the standard Markdown in a few significant ways to add some useful functionality.
41 37
@@ -49,7 +45,6 @@ You can use GFM in @@ -49,7 +45,6 @@ You can use GFM in
49 * milestones 45 * milestones
50 * wiki pages 46 * wiki pages
51 47
52 -<a name="newlines" />  
53 Newlines 48 Newlines
54 -------- 49 --------
55 The biggest difference that GFM introduces is in the handling of linebreaks. With traditional Markdown you can hard wrap paragraphs of text and they will be combined into a single paragraph. We find this to be the cause of a huge number of unintentional formatting errors. GFM treats newlines in paragraph-like content as real line breaks, which is probably what you intended. 50 The biggest difference that GFM introduces is in the handling of linebreaks. With traditional Markdown you can hard wrap paragraphs of text and they will be combined into a single paragraph. We find this to be the cause of a huge number of unintentional formatting errors. GFM treats newlines in paragraph-like content as real line breaks, which is probably what you intended.
@@ -61,8 +56,7 @@ The next paragraph contains two phrases separated by a single newline character: @@ -61,8 +56,7 @@ The next paragraph contains two phrases separated by a single newline character:
61 56
62 Roses are red 57 Roses are red
63 Violets are blue 58 Violets are blue
64 -  
65 -<a name="underscores" /> 59 +
66 Multiple underscores in words 60 Multiple underscores in words
67 ----------------------------- 61 -----------------------------
68 It is not reasonable to italicize just _part_ of a word, especially when you're dealing with code and names that often appear with multiple underscores. Therefore, GFM ignores multiple underscores in words. 62 It is not reasonable to italicize just _part_ of a word, especially when you're dealing with code and names that often appear with multiple underscores. Therefore, GFM ignores multiple underscores in words.
@@ -73,7 +67,6 @@ It is not reasonable to italicize just _part_ of a word, especially when you&#39;re @@ -73,7 +67,6 @@ It is not reasonable to italicize just _part_ of a word, especially when you&#39;re
73 perform_complicated_task 67 perform_complicated_task
74 do_this_and_do_that_and_another_thing 68 do_this_and_do_that_and_another_thing
75 69
76 -<a name="autolink" />  
77 URL autolinking 70 URL autolinking
78 --------------- 71 ---------------
79 GFM will autolink standard URLs you copy and paste into your text. 72 GFM will autolink standard URLs you copy and paste into your text.
@@ -83,12 +76,10 @@ So if you want to link to a URL (instead of a textural link), you can simply put @@ -83,12 +76,10 @@ So if you want to link to a URL (instead of a textural link), you can simply put
83 76
84 http://www.google.com 77 http://www.google.com
85 78
86 -<a name="code"/>  
87 ## Code and Syntax Highlighting 79 ## Code and Syntax Highlighting
88 80
89 Blocks of code are either fenced by lines with three back-ticks <code>```</code>, or are indented with four spaces. Only the fenced code blocks support syntax highlighting. 81 Blocks of code are either fenced by lines with three back-ticks <code>```</code>, or are indented with four spaces. Only the fenced code blocks support syntax highlighting.
90 82
91 -  
92 ```no-highlight 83 ```no-highlight
93 Inline `code` has `back-ticks around` it. 84 Inline `code` has `back-ticks around` it.
94 ``` 85 ```
@@ -101,14 +92,14 @@ Example: @@ -101,14 +92,14 @@ Example:
101 var s = "JavaScript syntax highlighting"; 92 var s = "JavaScript syntax highlighting";
102 alert(s); 93 alert(s);
103 ``` 94 ```
104 - 95 +
105 ```python 96 ```python
106 def function(): 97 def function():
107 #indenting works just fine in the fenced code block 98 #indenting works just fine in the fenced code block
108 s = "Python syntax highlighting" 99 s = "Python syntax highlighting"
109 print s 100 print s
110 ``` 101 ```
111 - 102 +
112 ```ruby 103 ```ruby
113 require 'redcarpet' 104 require 'redcarpet'
114 markdown = Redcarpet.new("Hello World!") 105 markdown = Redcarpet.new("Hello World!")
@@ -116,7 +107,7 @@ Example: @@ -116,7 +107,7 @@ Example:
116 ``` 107 ```
117 108
118 ``` 109 ```
119 - No language indicated, so no syntax highlighting. 110 + No language indicated, so no syntax highlighting.
120 s = "There is no highlighting for this." 111 s = "There is no highlighting for this."
121 But let's throw in a <b>tag</b>. 112 But let's throw in a <b>tag</b>.
122 ``` 113 ```
@@ -147,7 +138,6 @@ s = &quot;There is no highlighting for this.&quot; @@ -147,7 +138,6 @@ s = &quot;There is no highlighting for this.&quot;
147 But let's throw in a <b>tag</b>. 138 But let's throw in a <b>tag</b>.
148 ``` 139 ```
149 140
150 -<a name="emoji"/>  
151 Emoji 141 Emoji
152 ----- 142 -----
153 143
@@ -159,7 +149,7 @@ Emoji @@ -159,7 +149,7 @@ Emoji
159 149
160 If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes. 150 If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes.
161 151
162 - Consult the [Emoji Cheat Sheet](http://www.emoji-cheat-sheet.com/) for a list of all supported emoji codes. :thumbsup: 152 + Consult the [Emoji Cheat Sheet](http://www.emoji-cheat-sheet.com/) for a list of all supported emoji codes. :thumbsup:
163 153
164 Sometimes you want to be :cool: and add some :sparkles: to your :speech_balloon:. Well we have a :gift: for you: 154 Sometimes you want to be :cool: and add some :sparkles: to your :speech_balloon:. Well we have a :gift: for you:
165 155
@@ -169,9 +159,8 @@ You can use it to point out a :bug: or warn about :monkey:patches. And if someon @@ -169,9 +159,8 @@ You can use it to point out a :bug: or warn about :monkey:patches. And if someon
169 159
170 If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes. 160 If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes.
171 161
172 -Consult the [Emoji Cheat Sheet](http://www.emoji-cheat-sheet.com/) for a list of all supported emoji codes. :thumbsup: 162 +Consult the [Emoji Cheat Sheet](http://www.emoji-cheat-sheet.com/) for a list of all supported emoji codes. :thumbsup:
173 163
174 -<a name="special"/>  
175 Special GitLab References 164 Special GitLab References
176 ----- 165 -----
177 166
@@ -179,7 +168,6 @@ GFM recognized special references. @@ -179,7 +168,6 @@ GFM recognized special references.
179 You can easily reference e.g. a team member, an issue, or a commit within a project. 168 You can easily reference e.g. a team member, an issue, or a commit within a project.
180 GFM will turn that reference into a link so you can navigate between them easily. 169 GFM will turn that reference into a link so you can navigate between them easily.
181 170
182 -  
183 GFM will recognize the following: 171 GFM will recognize the following:
184 172
185 * @foo : for team members 173 * @foo : for team members
@@ -189,13 +177,10 @@ GFM will recognize the following: @@ -189,13 +177,10 @@ GFM will recognize the following:
189 * 1234567 : for commits 177 * 1234567 : for commits
190 * \[file\](path/to/file) : for file references 178 * \[file\](path/to/file) : for file references
191 179
192 -<a name="standard"/>  
193 -  
194 ---------------------------------- 180 ----------------------------------
195 # Standard Markdown 181 # Standard Markdown
196 182
197 ---------------------------------- 183 ----------------------------------
198 -<a name="headers"/>  
199 ## Headers 184 ## Headers
200 185
201 ```no-highlight 186 ```no-highlight
@@ -230,7 +215,54 @@ Alt-H1 @@ -230,7 +215,54 @@ Alt-H1
230 Alt-H2 215 Alt-H2
231 ------ 216 ------
232 217
233 -<a name="emphasis"/> 218 +### Header IDs and links
  219 +
  220 +All markdown rendered headers automatically get IDs, except for comments.
  221 +
  222 +On hover a link to those IDs becomes visible to make it easier to copy the link to the header to give it to someone else.
  223 +
  224 +The IDs are generated from the content of the header according to the following rules:
  225 +
  226 +1) remove the heading hashes `#` and process the rest of the line as it would be processed if it were not a header
  227 +2) from the result, remove all HTML tags, but keep their inner content
  228 +3) convert all characters to lowercase
  229 +4) convert all characters except `[a-z0-9_-]` into hyphens `-`
  230 +5) transform multiple adjacent hyphens into a single hyphen
  231 +6) remove trailing and heading hyphens
  232 +
  233 +For example:
  234 +
  235 +```
  236 +###### ..Ab_c-d. e [anchor](url) ![alt text](url)..
  237 +```
  238 +
  239 +which renders as:
  240 +
  241 +###### ..Ab_c-d. e [anchor](url) ![alt text](url)..
  242 +
  243 +will first be converted by step 1) into a string like:
  244 +
  245 +```
  246 +..Ab_c-d. e &lt;a href="url">anchor&lt;/a> &lt;img src="url" alt="alt text"/>..
  247 +```
  248 +
  249 +After removing the tags in step 2) we get:
  250 +
  251 +```
  252 +..Ab_c-d. e anchor ..
  253 +```
  254 +
  255 +And applying all the other steps gives the id:
  256 +
  257 +```
  258 +ab_c-d-e-anchor
  259 +```
  260 +
  261 +Note in particular how:
  262 +
  263 +- for markdown anchors `[text](url)`, only the `text` is used
  264 +- markdown images `![alt](url)` are completely ignored
  265 +
234 ## Emphasis 266 ## Emphasis
235 267
236 ```no-highlight 268 ```no-highlight
@@ -251,18 +283,16 @@ Combined emphasis with **asterisks and _underscores_**. @@ -251,18 +283,16 @@ Combined emphasis with **asterisks and _underscores_**.
251 283
252 Strikethrough uses two tildes. ~~Scratch this.~~ 284 Strikethrough uses two tildes. ~~Scratch this.~~
253 285
254 -  
255 -<a name="lists"/>  
256 ## Lists 286 ## Lists
257 287
258 ```no-highlight 288 ```no-highlight
259 1. First ordered list item 289 1. First ordered list item
260 2. Another item 290 2. Another item
261 - * Unordered sub-list. 291 + * Unordered sub-list.
262 1. Actual numbers don't matter, just that it's a number 292 1. Actual numbers don't matter, just that it's a number
263 1. Ordered sub-list 293 1. Ordered sub-list
264 -4. And another item.  
265 - 294 +4. And another item.
  295 +
266 Some text that should be aligned with the above item. 296 Some text that should be aligned with the above item.
267 297
268 * Unordered list can use asterisks 298 * Unordered list can use asterisks
@@ -272,18 +302,17 @@ Strikethrough uses two tildes. ~~Scratch this.~~ @@ -272,18 +302,17 @@ Strikethrough uses two tildes. ~~Scratch this.~~
272 302
273 1. First ordered list item 303 1. First ordered list item
274 2. Another item 304 2. Another item
275 - * Unordered sub-list. 305 + * Unordered sub-list.
276 1. Actual numbers don't matter, just that it's a number 306 1. Actual numbers don't matter, just that it's a number
277 1. Ordered sub-list 307 1. Ordered sub-list
278 -4. And another item.  
279 - 308 +4. And another item.
  309 +
280 Some text that should be aligned with the above item. 310 Some text that should be aligned with the above item.
281 311
282 * Unordered list can use asterisks 312 * Unordered list can use asterisks
283 - Or minuses 313 - Or minuses
284 + Or pluses 314 + Or pluses
285 315
286 -<a name="links"/>  
287 ## Links 316 ## Links
288 317
289 There are two ways to create links. 318 There are two ways to create links.
@@ -320,30 +349,28 @@ Some text to show that the reference links can follow later. @@ -320,30 +349,28 @@ Some text to show that the reference links can follow later.
320 [1]: http://slashdot.org 349 [1]: http://slashdot.org
321 [link text itself]: http://www.reddit.com 350 [link text itself]: http://www.reddit.com
322 351
323 -<a name="images"/>  
324 ## Images 352 ## Images
325 353
326 Here's our logo (hover to see the title text): 354 Here's our logo (hover to see the title text):
327 355
328 - Inline-style: 356 + Inline-style:
329 ![alt text](assets/logo-white.png) 357 ![alt text](assets/logo-white.png)
330 358
331 - Reference-style: 359 + Reference-style:
332 ![alt text1][logo] 360 ![alt text1][logo]
333 361
334 [logo]: assets/logo-white.png 362 [logo]: assets/logo-white.png
335 363
336 Here's our logo (hover to see the title text): 364 Here's our logo (hover to see the title text):
337 365
338 -Inline-style: 366 +Inline-style:
339 ![alt text](/assets/logo-white.png "Logo Title Text 1") 367 ![alt text](/assets/logo-white.png "Logo Title Text 1")
340 368
341 -Reference-style: 369 +Reference-style:
342 ![alt text][logo] 370 ![alt text][logo]
343 371
344 [logo]: /assets/logo-white.png "Logo Title Text 2" 372 [logo]: /assets/logo-white.png "Logo Title Text 2"
345 373
346 -<a name="blockquotes"/>  
347 ## Blockquotes 374 ## Blockquotes
348 375
349 ```no-highlight 376 ```no-highlight
@@ -352,7 +379,7 @@ Reference-style: @@ -352,7 +379,7 @@ Reference-style:
352 379
353 Quote break. 380 Quote break.
354 381
355 -> This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote. 382 +> This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote.
356 ``` 383 ```
357 384
358 > Blockquotes are very handy in email to emulate reply text. 385 > Blockquotes are very handy in email to emulate reply text.
@@ -360,12 +387,11 @@ Quote break. @@ -360,12 +387,11 @@ Quote break.
360 387
361 Quote break. 388 Quote break.
362 389
363 -> This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote. 390 +> This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote.
364 391
365 -<a name="html"/>  
366 ## Inline HTML 392 ## Inline HTML
367 393
368 -You can also use raw HTML in your Markdown, and it'll mostly work pretty well. 394 +You can also use raw HTML in your Markdown, and it'll mostly work pretty well.
369 395
370 ```no-highlight 396 ```no-highlight
371 <dl> 397 <dl>
@@ -385,7 +411,6 @@ You can also use raw HTML in your Markdown, and it&#39;ll mostly work pretty well. @@ -385,7 +411,6 @@ You can also use raw HTML in your Markdown, and it&#39;ll mostly work pretty well.
385 <dd>Does *not* work **very** well. Use HTML <em>tags</em>.</dd> 411 <dd>Does *not* work **very** well. Use HTML <em>tags</em>.</dd>
386 </dl> 412 </dl>
387 413
388 -<a name="hr"/>  
389 ## Horizontal Rule 414 ## Horizontal Rule
390 415
391 ``` 416 ```
@@ -418,10 +443,9 @@ ___ @@ -418,10 +443,9 @@ ___
418 443
419 Underscores 444 Underscores
420 445
421 -<a name="lines"/>  
422 ## Line Breaks 446 ## Line Breaks
423 447
424 -My basic recommendation for learning how line breaks work is to experiment and discover -- hit &lt;Enter&gt; once (i.e., insert one newline), then hit it twice (i.e., insert two newlines), see what happens. You'll soon learn to get what you want. "Markdown Toggle" is your friend. 448 +My basic recommendation for learning how line breaks work is to experiment and discover -- hit &lt;Enter&gt; once (i.e., insert one newline), then hit it twice (i.e., insert two newlines), see what happens. You'll soon learn to get what you want. "Markdown Toggle" is your friend.
425 449
426 Here are some things to try out: 450 Here are some things to try out:
427 451
@@ -438,11 +462,9 @@ Here&#39;s a line for us to start with. @@ -438,11 +462,9 @@ Here&#39;s a line for us to start with.
438 462
439 This line is separated from the one above by two newlines, so it will be a *separate paragraph*. 463 This line is separated from the one above by two newlines, so it will be a *separate paragraph*.
440 464
441 -This line is also begins a separate paragraph, but... 465 +This line is also begins a separate paragraph, but...
442 This line is only separated by a single newline, so it's a separate line in the *same paragraph*. 466 This line is only separated by a single newline, so it's a separate line in the *same paragraph*.
443 467
444 -  
445 -<a name="tables"/>  
446 ## Tables 468 ## Tables
447 469
448 Tables aren't part of the core Markdown spec, but they are part of GFM and Markdown Here supports them. 470 Tables aren't part of the core Markdown spec, but they are part of GFM and Markdown Here supports them.
@@ -461,10 +483,8 @@ Code above produces next output: @@ -461,10 +483,8 @@ Code above produces next output:
461 | cell 1 | cell 2 | 483 | cell 1 | cell 2 |
462 | cell 3 | cell 4 | 484 | cell 3 | cell 4 |
463 485
464 -  
465 ------------ 486 ------------
466 487
467 -<a name="references"/>  
468 ## References 488 ## References
469 489
470 * This document leveraged heavily from the [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). 490 * This document leveraged heavily from the [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
features/dashboard/help.feature 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +Feature: Help
  2 + Background:
  3 + Given I sign in as a user
  4 + And I visit the "Rake Tasks" help page
  5 +
  6 + Scenario: The markdown should be rendered correctly
  7 + Then I should see "Rake Tasks" page markdown rendered
  8 + And Header "Rebuild project satellites" should have correct ids and links
features/project/issues/issues.feature
@@ -55,3 +55,15 @@ Feature: Project Issues @@ -55,3 +55,15 @@ Feature: Project Issues
55 And I fill in issue search with ".3" 55 And I fill in issue search with ".3"
56 Then I should see "Release 0.3" in issues 56 Then I should see "Release 0.3" in issues
57 And I should not see "Release 0.4" in issues 57 And I should not see "Release 0.4" in issues
  58 +
  59 + # Markdown
  60 +
  61 + Scenario: Headers inside the description should have ids generated for them.
  62 + Given I visit issue page "Release 0.4"
  63 + Then Header "Description header" should have correct id and link
  64 +
  65 + @javascript
  66 + Scenario: Headers inside comments should not have ids generated for them.
  67 + Given I visit issue page "Release 0.4"
  68 + And I leave a comment with a header containing "Comment with a header"
  69 + Then The comment with the header should not have an ID
features/project/issues/milestones.feature
@@ -22,3 +22,9 @@ Feature: Project Milestones @@ -22,3 +22,9 @@ Feature: Project Milestones
22 Given the milestone has open and closed issues 22 Given the milestone has open and closed issues
23 And I click link "v2.2" 23 And I click link "v2.2"
24 Then I should see 3 issues 24 Then I should see 3 issues
  25 +
  26 + # Markdown
  27 +
  28 + Scenario: Headers inside the description should have ids generated for them.
  29 + Given I click link "v2.2"
  30 + Then Header "Description header" should have correct id and link
features/project/merge_requests.feature
@@ -77,3 +77,15 @@ Feature: Project Merge Requests @@ -77,3 +77,15 @@ Feature: Project Merge Requests
77 Then I modify merge commit message 77 Then I modify merge commit message
78 And I accept this merge request 78 And I accept this merge request
79 Then I should see merged request 79 Then I should see merged request
  80 +
  81 + # Markdown
  82 +
  83 + Scenario: Headers inside the description should have ids generated for them.
  84 + When I visit merge request page "Bug NS-04"
  85 + Then Header "Description header" should have correct id and link
  86 +
  87 + @javascript
  88 + Scenario: Headers inside comments should not have ids generated for them.
  89 + Given I visit merge request page "Bug NS-04"
  90 + And I leave a comment with a header containing "Comment with a header"
  91 + Then The comment with the header should not have an ID
features/project/source/markdown_render.feature
@@ -4,6 +4,15 @@ Feature: Project markdown render @@ -4,6 +4,15 @@ Feature: Project markdown render
4 And I own project "Delta" 4 And I own project "Delta"
5 Given I visit project source page 5 Given I visit project source page
6 6
  7 + # -------------------------------------------
  8 + # README
  9 + # -------------------------------------------
  10 +
  11 + Scenario: Tree view should have correct links in README
  12 + Given I go directory which contains README file
  13 + And I click on a relative link in README
  14 + Then I should see the correct markdown
  15 +
7 Scenario: I browse files from master branch 16 Scenario: I browse files from master branch
8 Then I should see files from repository in master 17 Then I should see files from repository in master
9 And I should see rendered README which contains correct links 18 And I should see rendered README which contains correct links
@@ -28,6 +37,14 @@ Feature: Project markdown render @@ -28,6 +37,14 @@ Feature: Project markdown render
28 And I click on Maintenance in README 37 And I click on Maintenance in README
29 Then I should see correct maintenance file rendered 38 Then I should see correct maintenance file rendered
30 39
  40 + Scenario: README headers should have header links
  41 + Then I should see rendered README which contains correct links
  42 + And Header "Application details" should have correct id and link
  43 +
  44 + # -------------------------------------------
  45 + # File content
  46 + # -------------------------------------------
  47 +
31 Scenario: I navigate to doc directory to view documentation in master 48 Scenario: I navigate to doc directory to view documentation in master
32 And I navigate to the doc/api/README 49 And I navigate to the doc/api/README
33 And I see correct file rendered 50 And I see correct file rendered
@@ -40,6 +57,14 @@ Feature: Project markdown render @@ -40,6 +57,14 @@ Feature: Project markdown render
40 And I click on raketasks in doc/api/README 57 And I click on raketasks in doc/api/README
41 Then I should see correct directory rendered 58 Then I should see correct directory rendered
42 59
  60 + Scenario: I navigate to doc directory to view user doc in master
  61 + And I navigate to the doc/api/README
  62 + And Header "GitLab API" should have correct id and link
  63 +
  64 + # -------------------------------------------
  65 + # Markdown branch README
  66 + # -------------------------------------------
  67 +
43 Scenario: I browse files from markdown branch 68 Scenario: I browse files from markdown branch
44 When I visit markdown branch 69 When I visit markdown branch
45 Then I should see files from repository in markdown branch 70 Then I should see files from repository in markdown branch
@@ -68,6 +93,10 @@ Feature: Project markdown render @@ -68,6 +93,10 @@ Feature: Project markdown render
68 And I click on raketasks in doc/api/README 93 And I click on raketasks in doc/api/README
69 Then I should see correct directory rendered for markdown branch 94 Then I should see correct directory rendered for markdown branch
70 95
  96 + # -------------------------------------------
  97 + # Wiki
  98 + # -------------------------------------------
  99 +
71 Scenario: I create a wiki page with different links 100 Scenario: I create a wiki page with different links
72 Given I go to wiki page 101 Given I go to wiki page
73 And I add various links to the wiki page 102 And I add various links to the wiki page
@@ -81,12 +110,7 @@ Feature: Project markdown render @@ -81,12 +110,7 @@ Feature: Project markdown render
81 And I click on Rake tasks link 110 And I click on Rake tasks link
82 Then I see Rake tasks directory 111 Then I see Rake tasks directory
83 112
84 - Scenario: I visit the help page with markdown  
85 - Given I visit to the help page  
86 - And I select a page with markdown  
87 - Then I should see a help page with markdown  
88 -  
89 - Scenario: Tree view should have correct links in README  
90 - Given I go directory which contains README file  
91 - And I click on a relative link in README  
92 - Then I should see the correct markdown 113 + Scenario: Wiki headers should have should have ids generated for them.
  114 + Given I go to wiki page
  115 + And I add a header to the wiki page
  116 + Then Wiki header should have correct id and link
features/steps/help.rb 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +class Spinach::Features::Help < Spinach::FeatureSteps
  2 + include SharedAuthentication
  3 + include SharedPaths
  4 + include SharedMarkdown
  5 +
  6 + step 'I visit the help page' do
  7 + visit help_path
  8 + end
  9 +
  10 + step 'I visit the "Rake Tasks" help page' do
  11 + visit help_raketasks_path
  12 + end
  13 +
  14 + step 'I should see "Rake Tasks" page markdown rendered' do
  15 + page.should have_content "GitLab provides some specific rake tasks to enable special features or perform maintenance tasks"
  16 + end
  17 +
  18 + step 'Header "Rebuild project satellites" should have correct ids and links' do
  19 + header_should_have_correct_id_and_link(3, 'Rebuild project satellites', 'rebuild-project-satellites')
  20 + end
  21 +end
features/steps/project/project_issues.rb
@@ -3,6 +3,7 @@ class ProjectIssues &lt; Spinach::FeatureSteps @@ -3,6 +3,7 @@ class ProjectIssues &lt; Spinach::FeatureSteps
3 include SharedProject 3 include SharedProject
4 include SharedNote 4 include SharedNote
5 include SharedPaths 5 include SharedPaths
  6 + include SharedMarkdown
6 7
7 Given 'I should see "Release 0.4" in issues' do 8 Given 'I should see "Release 0.4" in issues' do
8 page.should have_content "Release 0.4" 9 page.should have_content "Release 0.4"
@@ -121,7 +122,9 @@ class ProjectIssues &lt; Spinach::FeatureSteps @@ -121,7 +122,9 @@ class ProjectIssues &lt; Spinach::FeatureSteps
121 create(:issue, 122 create(:issue,
122 title: "Release 0.4", 123 title: "Release 0.4",
123 project: project, 124 project: project,
124 - author: project.users.first) 125 + author: project.users.first,
  126 + description: "# Description header"
  127 + )
125 end 128 end
126 129
127 And 'project "Shop" have "Tweet control" open issue' do 130 And 'project "Shop" have "Tweet control" open issue' do
features/steps/project/project_markdown_render.rb
1 class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps 1 class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps
2 include SharedAuthentication 2 include SharedAuthentication
3 include SharedPaths 3 include SharedPaths
  4 + include SharedMarkdown
4 5
5 And 'I own project "Delta"' do 6 And 'I own project "Delta"' do
6 @project = Project.find_by(name: "Delta") 7 @project = Project.find_by(name: "Delta")
@@ -44,7 +45,6 @@ class Spinach::Features::ProjectMarkdownRender &lt; Spinach::FeatureSteps @@ -44,7 +45,6 @@ class Spinach::Features::ProjectMarkdownRender &lt; Spinach::FeatureSteps
44 page.should have_content "maintenance.md" 45 page.should have_content "maintenance.md"
45 end 46 end
46 47
47 -  
48 And 'I click on GitLab API doc directory in README' do 48 And 'I click on GitLab API doc directory in README' do
49 click_link "GitLab API doc directory" 49 click_link "GitLab API doc directory"
50 end 50 end
@@ -140,6 +140,16 @@ class Spinach::Features::ProjectMarkdownRender &lt; Spinach::FeatureSteps @@ -140,6 +140,16 @@ class Spinach::Features::ProjectMarkdownRender &lt; Spinach::FeatureSteps
140 page.should have_content "test GitLab API doc Rake tasks" 140 page.should have_content "test GitLab API doc Rake tasks"
141 end 141 end
142 142
  143 + step 'I add a header to the wiki page' do
  144 + fill_in "wiki[content]", with: "# Wiki header\n"
  145 + fill_in "wiki[message]", with: "Add header to wiki"
  146 + click_button "Create page"
  147 + end
  148 +
  149 + step 'Wiki header should have correct id and link' do
  150 + header_should_have_correct_id_and_link(1, 'Wiki header', 'wiki-header')
  151 + end
  152 +
143 And 'I click on test link' do 153 And 'I click on test link' do
144 click_link "test" 154 click_link "test"
145 end 155 end
@@ -173,18 +183,6 @@ class Spinach::Features::ProjectMarkdownRender &lt; Spinach::FeatureSteps @@ -173,18 +183,6 @@ class Spinach::Features::ProjectMarkdownRender &lt; Spinach::FeatureSteps
173 page.should have_content "maintenance.md" 183 page.should have_content "maintenance.md"
174 end 184 end
175 185
176 - Given 'I visit to the help page' do  
177 - visit help_path  
178 - end  
179 -  
180 - And 'I select a page with markdown' do  
181 - click_link "Rake Tasks"  
182 - end  
183 -  
184 - Then 'I should see a help page with markdown' do  
185 - page.should have_content "GitLab provides some specific rake tasks to enable special features or perform maintenance tasks"  
186 - end  
187 -  
188 Given 'I go directory which contains README file' do 186 Given 'I go directory which contains README file' do
189 visit project_tree_path(@project, "master/doc/api") 187 visit project_tree_path(@project, "master/doc/api")
190 current_path.should == project_tree_path(@project, "master/doc/api") 188 current_path.should == project_tree_path(@project, "master/doc/api")
@@ -198,4 +196,12 @@ class Spinach::Features::ProjectMarkdownRender &lt; Spinach::FeatureSteps @@ -198,4 +196,12 @@ class Spinach::Features::ProjectMarkdownRender &lt; Spinach::FeatureSteps
198 current_path.should == project_blob_path(@project, "master/doc/api/users.md") 196 current_path.should == project_blob_path(@project, "master/doc/api/users.md")
199 page.should have_content "List users" 197 page.should have_content "List users"
200 end 198 end
  199 +
  200 + step 'Header "Application details" should have correct id and link' do
  201 + header_should_have_correct_id_and_link(2, 'Application details', 'application-details')
  202 + end
  203 +
  204 + step 'Header "GitLab API" should have correct id and link' do
  205 + header_should_have_correct_id_and_link(1, 'GitLab API', 'gitlab-api')
  206 + end
201 end 207 end
features/steps/project/project_merge_requests.rb
@@ -3,6 +3,7 @@ class ProjectMergeRequests &lt; Spinach::FeatureSteps @@ -3,6 +3,7 @@ class ProjectMergeRequests &lt; Spinach::FeatureSteps
3 include SharedProject 3 include SharedProject
4 include SharedNote 4 include SharedNote
5 include SharedPaths 5 include SharedPaths
  6 + include SharedMarkdown
6 7
7 step 'I click link "New Merge Request"' do 8 step 'I click link "New Merge Request"' do
8 click_link "New Merge Request" 9 click_link "New Merge Request"
@@ -83,7 +84,9 @@ class ProjectMergeRequests &lt; Spinach::FeatureSteps @@ -83,7 +84,9 @@ class ProjectMergeRequests &lt; Spinach::FeatureSteps
83 target_project: project, 84 target_project: project,
84 source_branch: 'stable', 85 source_branch: 'stable',
85 target_branch: 'master', 86 target_branch: 'master',
86 - author: project.users.first) 87 + author: project.users.first,
  88 + description: "# Description header"
  89 + )
87 end 90 end
88 91
89 step 'project "Shop" have "Bug NS-05" open merge request with diffs inside' do 92 step 'project "Shop" have "Bug NS-05" open merge request with diffs inside' do
features/steps/project/project_milestones.rb
@@ -2,6 +2,7 @@ class ProjectMilestones &lt; Spinach::FeatureSteps @@ -2,6 +2,7 @@ class ProjectMilestones &lt; Spinach::FeatureSteps
2 include SharedAuthentication 2 include SharedAuthentication
3 include SharedProject 3 include SharedProject
4 include SharedPaths 4 include SharedPaths
  5 + include SharedMarkdown
5 6
6 Then 'I should see milestone "v2.2"' do 7 Then 'I should see milestone "v2.2"' do
7 milestone = @project.milestones.find_by(title: "v2.2") 8 milestone = @project.milestones.find_by(title: "v2.2")
@@ -32,8 +33,11 @@ class ProjectMilestones &lt; Spinach::FeatureSteps @@ -32,8 +33,11 @@ class ProjectMilestones &lt; Spinach::FeatureSteps
32 33
33 And 'project "Shop" has milestone "v2.2"' do 34 And 'project "Shop" has milestone "v2.2"' do
34 project = Project.find_by(name: "Shop") 35 project = Project.find_by(name: "Shop")
35 - milestone = create(:milestone, title: "v2.2", project: project)  
36 - 36 + milestone = create(:milestone,
  37 + title: "v2.2",
  38 + project: project,
  39 + description: "# Description header"
  40 + )
37 3.times { create(:issue, project: project, milestone: milestone) } 41 3.times { create(:issue, project: project, milestone: milestone) }
38 end 42 end
39 43
features/steps/shared/markdown.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +module SharedMarkdown
  2 + include Spinach::DSL
  3 +
  4 + def header_should_have_correct_id_and_link(level, text, id, parent = ".wiki")
  5 + page.find(:css, "#{parent} h#{level}##{id}").text.should == text
  6 + page.find(:css, "#{parent} h#{level}##{id} > :last-child")[:href].should =~ /##{id}$/
  7 + end
  8 +
  9 + step 'Header "Description header" should have correct id and link' do
  10 + header_should_have_correct_id_and_link(1, 'Description header', 'description-header')
  11 + end
  12 +end
features/steps/shared/note.rb
@@ -102,4 +102,21 @@ module SharedNote @@ -102,4 +102,21 @@ module SharedNote
102 page.should have_content("XML attached") 102 page.should have_content("XML attached")
103 end 103 end
104 end 104 end
  105 +
  106 + # Markdown
  107 +
  108 + step 'I leave a comment with a header containing "Comment with a header"' do
  109 + within(".js-main-target-form") do
  110 + fill_in "note[note]", with: "# Comment with a header"
  111 + click_button "Add Comment"
  112 + sleep 0.05
  113 + end
  114 + end
  115 +
  116 + step 'The comment with the header should not have an ID' do
  117 + within(".note-text") do
  118 + page.should have_content("Comment with a header")
  119 + page.should_not have_css("#comment-with-a-header")
  120 + end
  121 + end
105 end 122 end
lib/redcarpet/render/gitlab_html.rb
@@ -8,6 +8,7 @@ class Redcarpet::Render::GitlabHTML &lt; Redcarpet::Render::HTML @@ -8,6 +8,7 @@ class Redcarpet::Render::GitlabHTML &lt; Redcarpet::Render::HTML
8 @project = @template.instance_variable_get("@project") 8 @project = @template.instance_variable_get("@project")
9 @ref = @template.instance_variable_get("@ref") 9 @ref = @template.instance_variable_get("@ref")
10 @request_path = @template.instance_variable_get("@path") 10 @request_path = @template.instance_variable_get("@path")
  11 + @options = options.dup
11 super options 12 super options
12 end 13 end
13 14
@@ -34,6 +35,16 @@ class Redcarpet::Render::GitlabHTML &lt; Redcarpet::Render::HTML @@ -34,6 +35,16 @@ class Redcarpet::Render::GitlabHTML &lt; Redcarpet::Render::HTML
34 h.link_to_gfm(content, link, title: title) 35 h.link_to_gfm(content, link, title: title)
35 end 36 end
36 37
  38 + def header(text, level)
  39 + if @options[:no_header_anchors]
  40 + "<h#{level}>#{text}</h#{level}>"
  41 + else
  42 + id = ActionController::Base.helpers.strip_tags(h.gfm(text)).downcase() \
  43 + .gsub(/[^a-z0-9_-]/, '-').gsub(/-+/, '-').gsub(/^-/, '').gsub(/-$/, '')
  44 + "<h#{level} id=\"#{id}\">#{text}<a href=\"\##{id}\"></a></h#{level}>"
  45 + end
  46 + end
  47 +
37 def preprocess(full_document) 48 def preprocess(full_document)
38 if @project 49 if @project
39 h.create_relative_links(full_document, @project, @ref, @request_path, is_wiki?) 50 h.create_relative_links(full_document, @project, @ref, @request_path, is_wiki?)
spec/helpers/gitlab_markdown_helper_spec.rb
@@ -348,8 +348,21 @@ describe GitlabMarkdownHelper do @@ -348,8 +348,21 @@ describe GitlabMarkdownHelper do
348 it "should handle references in headers" do 348 it "should handle references in headers" do
349 actual = "\n# Working around ##{issue.iid}\n## Apply !#{merge_request.iid}" 349 actual = "\n# Working around ##{issue.iid}\n## Apply !#{merge_request.iid}"
350 350
351 - markdown(actual).should match(%r{<h1[^<]*>Working around <a.+>##{issue.iid}</a></h1>})  
352 - markdown(actual).should match(%r{<h2[^<]*>Apply <a.+>!#{merge_request.iid}</a></h2>}) 351 + markdown(actual, {no_header_anchors:true}).should match(%r{<h1[^<]*>Working around <a.+>##{issue.iid}</a></h1>})
  352 + markdown(actual, {no_header_anchors:true}).should match(%r{<h2[^<]*>Apply <a.+>!#{merge_request.iid}</a></h2>})
  353 + end
  354 +
  355 + it "should add ids and links to headers" do
  356 + # Test every rule except nested tags.
  357 + text = '..Ab_c-d. e..'
  358 + id = 'ab_c-d-e'
  359 + markdown("# #{text}").should match(%r{<h1 id="#{id}">#{text}<a href="[^"]*##{id}"></a></h1>})
  360 + markdown("# #{text}", {no_header_anchors:true}).should == "<h1>#{text}</h1>"
  361 +
  362 + id = 'link-text'
  363 + markdown("# [link text](url) ![img alt](url)").should match(
  364 + %r{<h1 id="#{id}"><a href="[^"]*url">link text</a> <img[^>]*><a href="[^"]*##{id}"></a></h1>}
  365 + )
353 end 366 end
354 367
355 it "should handle references in lists" do 368 it "should handle references in lists" do