Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefix all user-generated IDs in markup #9477

Merged
merged 7 commits into from
Dec 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions modules/markup/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ var (
emailRegex = regexp.MustCompile("(?:\\s|^|\\(|\\[)([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]{2,}(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)(?:\\s|$|\\)|\\]|\\.(\\s|$))")

linkRegex, _ = xurls.StrictMatchingScheme("https?://")

// blackfriday extensions create IDs like fn:user-content-footnote
blackfridayExtRegex = regexp.MustCompile(`[^:]*:user-content-`)
)

// CSS class for action keywords (e.g. "closes: #1")
Expand Down Expand Up @@ -312,6 +315,12 @@ func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) {
}

func (ctx *postProcessCtx) visitNode(node *html.Node) {
// Add user-content- to IDs if they don't already have them
for idx, attr := range node.Attr {
if attr.Key == "id" && !(strings.HasPrefix(attr.Val, "user-content-") || blackfridayExtRegex.MatchString(attr.Val)) {
node.Attr[idx].Val = "user-content-" + attr.Val
}
}
// We ignore code, pre and already generated links.
switch node.Type {
case html.TextNode:
Expand Down
4 changes: 3 additions & 1 deletion modules/markup/markdown/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ const (
func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
renderer := &Renderer{
Renderer: blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{
Flags: blackfridayHTMLFlags,
Flags: blackfridayHTMLFlags,
FootnoteAnchorPrefix: "user-content-",
HeadingIDPrefix: "user-content-",
}),
URLPrefix: urlPrefix,
IsWiki: wikiMarkdown,
Expand Down
16 changes: 8 additions & 8 deletions modules/markup/markdown/markdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
<li><a href="` + baseURLContent + `/plot_var_example" rel="nofollow">Plot var helper</a></li>
</ul>
`,
`<h2 id="what-is-wine-staging">What is Wine Staging?</h2>
`<h2 id="user-content-what-is-wine-staging">What is Wine Staging?</h2>

<p><strong>Wine Staging</strong> on website <a href="http://wine-staging.com" rel="nofollow">wine-staging.com</a>.</p>

<h2 id="quick-links">Quick Links</h2>
<h2 id="user-content-quick-links">Quick Links</h2>

<p>Here are some links to the most important topics. You can find the full list of pages at the sidebar.</p>

Expand Down Expand Up @@ -149,11 +149,11 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
<a href="` + baseURLImages + `/images/2.png" rel="nofollow"><img src="` + baseURLImages + `/images/2.png" title="2.png" alt="images/2.png"/></a></li>
</ol>

<h2 id="custom-id">More tests</h2>
<h2 id="user-content-custom-id">More tests</h2>

<p>(from <a href="https://www.markdownguide.org/extended-syntax/" rel="nofollow">https://www.markdownguide.org/extended-syntax/</a>)</p>

<h3 id="definition-list">Definition list</h3>
<h3 id="user-content-definition-list">Definition list</h3>

<dl>
<dt>First Term</dt>
Expand All @@ -163,18 +163,18 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
<dd>This is another definition of the second term.</dd>
</dl>

<h3 id="footnotes">Footnotes</h3>
<h3 id="user-content-footnotes">Footnotes</h3>

<p>Here is a simple footnote,<sup id="fnref:1"><a href="#fn:1" rel="nofollow">1</a></sup> and here is a longer one.<sup id="fnref:bignote"><a href="#fn:bignote" rel="nofollow">2</a></sup></p>
<p>Here is a simple footnote,<sup id="fnref:user-content-1"><a href="#fn:user-content-1" rel="nofollow">1</a></sup> and here is a longer one.<sup id="fnref:user-content-bignote"><a href="#fn:user-content-bignote" rel="nofollow">2</a></sup></p>

<div>

<hr/>

<ol>
<li id="fn:1">This is the first footnote.</li>
<li id="fn:user-content-1">This is the first footnote.</li>

<li id="fn:bignote"><p>Here is one with multiple paragraphs and code.</p>
<li id="fn:user-content-bignote"><p>Here is one with multiple paragraphs and code.</p>

<p>Indent paragraphs to include them in the footnote.</p>

Expand Down
4 changes: 2 additions & 2 deletions routers/api/v1/misc/markdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ Here are some links to the most important topics. You can find the full list of
[[images/icon-bug.png]]
`,
// rendered
`<h2 id="what-is-wine-staging">What is Wine Staging?</h2>
`<h2 id="user-content-what-is-wine-staging">What is Wine Staging?</h2>

<p><strong>Wine Staging</strong> on website <a href="http://wine-staging.com" rel="nofollow">wine-staging.com</a>.</p>

<h2 id="quick-links">Quick Links</h2>
<h2 id="user-content-quick-links">Quick Links</h2>

<p>Here are some links to the most important topics. You can find the full list of pages at the sidebar.</p>

Expand Down
15 changes: 2 additions & 13 deletions web_src/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2472,21 +2472,10 @@ $(document).ready(() => {

// Set anchor.
$('.markdown').each(function () {
const headers = {};
$(this).find('h1, h2, h3, h4, h5, h6').each(function () {
let node = $(this);
const val = encodeURIComponent(node.text().toLowerCase().replace(/[^\u00C0-\u1FFF\u2C00-\uD7FF\w\- ]/g, '').replace(/[ ]/g, '-'));
let name = val;
if (headers[val] > 0) {
name = `${val}-${headers[val]}`;
}
if (headers[val] === undefined) {
headers[val] = 1;
} else {
headers[val] += 1;
}
node = node.wrap(`<div id="${name}" class="anchor-wrap" ></div>`);
node.append(`<a class="anchor" href="#${name}"><span class="octicon octicon-link"></span></a>`);
node = node.wrap('<div class="anchor-wrap"></div>');
node.append(`<a class="anchor" href="#${encodeURIComponent(node.attr('id'))}"><span class="octicon octicon-link"></span></a>`);
});
});

Expand Down