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

Markdown rendering overhaul #186

Merged
merged 2 commits into from
Feb 14, 2017
Merged

Markdown rendering overhaul #186

merged 2 commits into from
Feb 14, 2017

Conversation

andrew-boyarshin
Copy link
Contributor

The majority of markdown files should now look great.

  1. Implemented sidebar and footer (GitHub like). Header can also be done, but even GitHub doesn't implement one.
  2. Implemented [[...]] image & link handling. It is quite a feature. It supports a variety of syntaxes.
![logo](http://libgdx.badlogicgames.com/img/logo.png)
[[[https://d3js.org/logo.svg|alt="D3js Logo"|height=210px|width=210px]]](https://d3js.org)
[[https://d3js.org/logo.svg|alt="D3js Logo"|height=210px|width=210px]]
[[Install]]
[[my internal link|internal-ref]]
![](000 hello world.png)
It is my great responsibility to send you... to http://google.com in order to find all your answers there.
The point is, <https://google.com> is more correct.
[Wiki](Home)**API Reference**
[[semantic versioning|http://semver.org]]
[[images/icon-install.png]]
  1. Added the ability to display any kind of text blobs with rendering as Markdown. For example guard uses Textile for its Home wiki page. Textile and markdown have common roots, so that it renders perfectly with Markdown parser. Anyway, it is better to display something, than to display nothing.
  2. Fixed a bug in markdown parser (stopped any special formatting after non-closeable tags like img)
  3. I've mirrored about 15 wikis. Everything renders fine, all images are resolved perfectly (even html hardcoded should work in most cases).

@codecov-io
Copy link

codecov-io commented Nov 16, 2016

Codecov Report

❗ No coverage uploaded for pull request base (master@b6dd621). Click here to learn what that means.

@@           Coverage Diff            @@
##             master    #186   +/-   ##
========================================
  Coverage          ?   5.27%           
========================================
  Files             ?      33           
  Lines             ?    8272           
  Branches          ?       0           
========================================
  Hits              ?     436           
  Misses            ?    7793           
  Partials          ?      43
Impacted Files Coverage Δ
models/mail.go 0% <ø> (ø)
modules/markdown/markdown.go 66.76% <65.8%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b6dd621...1e95e95. Read the comment docs.

@@ -580,6 +580,11 @@ func runWeb(ctx *cli.Context) error {
}, reqSignIn, reqRepoWriter)
}, repo.MustEnableWiki, context.RepoRef())

m.Group("/wiki", func() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to the Markdown rendering?

Copy link
Contributor Author

@andrew-boyarshin andrew-boyarshin Nov 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@metalmatze Related closely. To support all types of embedding images into markdown files (both in wiki and repo itself) I changed wiki content loading scheme. Without this change markdown files with HTML <img> tags inside would fail to load pictures.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, no problem. Just seemed unrelated to me at first glance.


WikiLinkPattern = regexp.MustCompile(`(\[\[.*\]\]\w*)`)

/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would you commit all this? 😊

Copy link
Contributor Author

@andrew-boyarshin andrew-boyarshin Nov 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@metalmatze I can't quite catch the meaning. It is necessary for the system to work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think he's talking about the examples for the matches below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly. 😊

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move those patterns into a unit-test instead ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bkcsoft will do!

Copy link
Member

@bkcsoft bkcsoft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go fmt and go lint after these

@@ -271,6 +346,212 @@ func RenderSha1CurrentPattern(rawBytes []byte, urlPrefix string) []byte {
}))
}

func RenderFullSha1Pattern(rawBytes []byte, urlPrefix string) []byte {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these exported?

@@ -43,33 +47,186 @@ type PageMeta struct {
Updated time.Time
}

func renderWikiPage(ctx *context.Context, isViewPage bool) (*git.Repository, string) {
func UrlEncoded(str string) string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these two should not be exported?

@andreynering andreynering added the type/enhancement An improvement of existing functionality label Nov 16, 2016
Copy link
Contributor

@andreynering andreynering left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR, this seems a very good addition. 👍

I just made some comments. Remove commented code, run go fmt, maybe add some test cases.

case bytes.HasPrefix(text, []byte("[x] ")):
text = append([]byte(`<input type="checkbox" disabled="" checked="" />`), text[3:]...)
case bytes.HasPrefix(text, []byte(prefix+"[ ] ")):
text = append([]byte(`<div class="ui fitted read-only checkbox"><input type="checkbox" /><label /></div>`), text[3+len(prefix):]...)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing disabled attribute on checkbox?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andreynering yes, to remove awful grey shadow over the checkbox I used read-only instead of disabled. In fact, it only influences appearance.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer the old disabled here.

Also, the checkbox should also be disabled while previewing changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andreynering will change.

Also, the checkbox should also be disabled while previewing changes.

Uhm... you mean markdown editor frontend? Or what?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean markdown editor frontend?

Yes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andreynering it is theme for another PR, isn't it? I'm not exactly sure how to do it at the moment, in fact, gogs/gitea frontend is quite an unknown land for me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bug, so should be fixed in this PR. I will take a look on what caused it when I have a little time. 👍

For future contributions, I think it's a good idea to split big features in more PRs. It makes it easier and faster to review.

Let me know if you need help with this. We can push your branch to the main repo, so more people would have write access to it.

}
}
/*
for k, v := range props {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove all commented code

@@ -300,9 +584,9 @@ func RenderRaw(body []byte, urlPrefix string) []byte {
extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
extensions |= blackfriday.EXTENSION_TABLES
extensions |= blackfriday.EXTENSION_FENCED_CODE
extensions |= blackfriday.EXTENSION_AUTOLINK
//extensions |= blackfriday.EXTENSION_AUTOLINK
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this necessary anymore? If not maybe we can delete them

extensions |= blackfriday.EXTENSION_STRIKETHROUGH
extensions |= blackfriday.EXTENSION_SPACE_HEADERS
// extensions |= blackfriday.EXTENSION_SPACE_HEADERS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above


func RenderWiki(rawBytes []byte, urlPrefix string, metas map[string]string) string {
defer func() { isWikiMarkdown = false }()
isWikiMarkdown = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Global variables are bad. Maybe this can be a function argument?

@@ -594,6 +594,7 @@ function initWikiForm() {
function (data) {
preview.innerHTML = '<div class="markdown">' + data + '</div>';
emojify.run($('.editor-preview')[0]);
$('.editor-preview').autolink();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to move this from backend to frontend?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andreynering I've experimented hard with it for a long time. Often rendering on backend resulted in broken children links or image links. So instead it is now done on frontend, with a better, conservative yet effective implementation, which operates the DOM, not the wall of text. No links or image urls are now broken, as now it respects tags and their children. It is quite fast, and it offloads servers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO that should be done on the backend, otherwise it will never get indexed for public wikis

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@STALKER2010 it's also frontend?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only preview, so put it in front-end?

Copy link
Contributor Author

@andrew-boyarshin andrew-boyarshin Feb 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lunny (1st message) yes, as server-side autolinking often pulled apart tags, attributes. On client side we can manipulate DOM the way we want to, with no harm done to structure.
@tboerger about search engine indexing.
Default <http://google.com> markdown syntax is always done on server side. Autolinking in plain text is not defined by any markdown standard, so it's just nice stuff to have. If we do plain text autolinking on server, we can corrupt the whole document. Wrong thing to do, so I disabled it. If we do it on client, we may not linkify all possible links, but we do it in much safer way for the document. So, why not. Even if user has disabled JS in his browser, standard links will still work, plain text will not. Better than rendering corrupted document either way. Plus, most popular search engines (like Google, Bing, Yandex) execute JavaScript, so no harm done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lunny (2nd question) no, as you see below, it is for both editor preview and final rendering. Reasoning is shown above.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

most popular search engines (like Google, Bing, Yandex) execute JavaScript, so no harm done.

They also infer a penalty for changing the context in JS 🙁

Copy link
Contributor Author

@andrew-boyarshin andrew-boyarshin Feb 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bkcsoft the context? You mean, the web page content? I've looked it up, googled it and found no reference of any penalty. What I did find is that Google does not always run JS. Yet, I bet Google crawler is smart enough to do autolinking itself. And even if it isn't, the standard Markdown links should work flawlessly, we only lose unnecessary standard extensions. If anyone is willing to implement autolinking server-side after merging this PR, I would be glad to hear it.

@@ -1361,6 +1362,7 @@ $(document).ready(function () {
node.append('<a class="anchor" href="#' + name + '"><span class="octicon octicon-link"></span></a>');
});
});
$('.markdown').autolink();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

}
return nil, git.ErrNotExist{"", target}
}
func _commitTreeEntry(repo *git.Repository, commit *git.Commit, target string, wikiOnly bool) (*git.TreeEntry, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't prefix functions with _

rawBytes = RenderIssueIndexPattern(rawBytes, urlPrefix, metas)
rawBytes = RenderSha1CurrentPattern(rawBytes, urlPrefix)
//rawBytes = RenderSha1CurrentPattern(rawBytes, urlPrefix)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't we need this anymore?

@strk
Copy link
Member

strk commented Nov 17, 2016

What's the milestone for this ?

@lunny lunny added this to the 1.1.0 milestone Nov 17, 2016
@andrew-boyarshin
Copy link
Contributor Author

Fixing all weak areas of PR, writing some additional tests, improving test coverage. I hope it will be done by weekends.

@andreynering andreynering added the issue/needs-feedback For bugs, we need more details. For features, the feature must be described in more detail label Nov 19, 2016
@andrew-boyarshin
Copy link
Contributor Author

andrew-boyarshin commented Nov 20, 2016

Ready to review once again. Coverage of markdown.go increased significantly, new tests cover more than half of the code (about 65%, compared to about 25% before the PR), greatly improved wiki page loading (rewritten system, optimizing and improving architecture and code itself). Made some changes to Markdown API, so that all systems work with changes. Fixed bugs found, now markdown files look even better.
It would be nice to get this into 1.0 release too!

@andreynering andreynering removed the issue/needs-feedback For bugs, we need more details. For features, the feature must be described in more detail label Nov 20, 2016
Copy link
Contributor

@andreynering andreynering left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's still minor things that needs addressing.

case bytes.HasPrefix(text, []byte("[x] ")):
text = append([]byte(`<input type="checkbox" disabled="" checked="" />`), text[3:]...)
case bytes.HasPrefix(text, []byte(prefix+"[ ] ")):
text = append([]byte(`<div class="ui fitted read-only checkbox"><input type="checkbox" /><label /></div>`), text[3+len(prefix):]...)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer the old disabled here.

Also, the checkbox should also be disabled while previewing changes.

}

// renderFullIssuePattern renders issues-like URLs
func renderFullIssuePattern(rawBytes []byte, repoLink, urlPrefix string) []byte {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found problems with issue pattern rendering.

Link https://github.com/go-gitea/gitea/pull/186 renders to:

  • Title: #186
  • Preview URL: http://localhost:3000/issues/186
  • After saved URL: http://localhost:3000/andreynering/mylocalrepo/issues/186

Link https://github.com/go-gitea/gitea/pull/186/files renders to:

  • Title: #186/files
  • Preview URL: http://localhost:3000/issues/186
  • After saved URL: http://localhost:3000/andreynering/mylocalrepo/issues/186

The original URL should be preserved. It can refer to GitHub or another Gitea instance, as example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andreynering will look into the case, not sure at the moment what to do with that.

Sha1CurrentPattern = regexp.MustCompile(`(?:^|\s|\()[0-9a-f]{40}\b`)

// WikiLinkPattern matches difficult [[link syntax]]
WikiLinkPattern = regexp.MustCompile(`(\[\[.*\]\]\w*)`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed these kind of link always point to wiki. Is this intentional?

Example: [[foobar]] on README.md will refer to /user/repo/wiki/foobar and not a file called foobar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andreynering yes, it is, it can be changed though. I've just never seen a single repo with markdown file in it using [[syntax]]. Shall I implement it for repo too?

. "github.com/smartystreets/goconvey/convey"
)

func TestMarkdown(t *testing.T) {
setting.AppUrl = "http://gogs/"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oldAppUrl := setting.AppUrl
defer func() {
    setting.AppUrl = oldAppUrl
}()
setting.AppUrl = "http://gogs/"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

@lunny
Copy link
Member

lunny commented Dec 25, 2016

This need rebase and review continue!

@tboerger tboerger added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Dec 25, 2016
@tboerger
Copy link
Member

Still in conflicting state

@tboerger tboerger added the issue/needs-feedback For bugs, we need more details. For features, the feature must be described in more detail label Dec 29, 2016
@Bwko
Copy link
Member

Bwko commented Jan 11, 2017

@STALKER2010 Any updates on this?

@lunny
Copy link
Member

lunny commented Jan 26, 2017

if nobody want to takeover this one, I will move it to v1.2

@lunny lunny modified the milestones: 1.2.0, 1.1.0 Feb 7, 2017
@lunny
Copy link
Member

lunny commented Feb 9, 2017

Please rebase.

@andrew-boyarshin
Copy link
Contributor Author

@lunny In progress. Test system rework was quite a change.

@andrew-boyarshin
Copy link
Contributor Author

andrew-boyarshin commented Feb 9, 2017

Could someone explain why the build failed? I can only see lint suggestions, not in my code.
P.S. Looks like common PR issue.

@andrew-boyarshin
Copy link
Contributor Author

andrew-boyarshin commented Feb 9, 2017

Looks like Windows has done some strange stuff to file permissions. Fixing...
Wow. Git made such a mess...

@lunny
Copy link
Member

lunny commented Feb 9, 2017

Please rebase, it seems there are many unused changes.

Cleaned up and squashed commits into single one.

Signed-off-by: Andrew Boyarshin <[email protected]>
@andrew-boyarshin
Copy link
Contributor Author

andrew-boyarshin commented Feb 9, 2017

@lunny Done. Had to recreate branch and export all changes to patch file due to merge conflicts in the past and Windows file permissions change recently. Also squashed all commits into one.
Anyone willing to review?

@@ -26,9 +26,9 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) {

switch form.Mode {
case "gfm":
ctx.Write(markdown.Render([]byte(form.Text), form.Context, nil))
ctx.Write(markdown.Render([]byte(form.Text), ctx.Repo.RepoLink, nil))
Copy link
Contributor Author

@andrew-boyarshin andrew-boyarshin Feb 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not quite sure about this one. I can't recall doing that. Any thoughts? Is it good or bad?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe repo.HTMLUrl() ?

Copy link
Contributor Author

@andrew-boyarshin andrew-boyarshin Feb 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lunny Hmm... Three different variants. Perhaps, invite more reviewers? Opinions matter.

@lunny
Copy link
Member

lunny commented Feb 9, 2017

Great. I will review this.

@lunny
Copy link
Member

lunny commented Feb 9, 2017

It seems this PR could not fix #652 ?

@tboerger tboerger added the lgtm/need 1 This PR needs approval from one additional maintainer to be merged. label Feb 9, 2017
@lunny lunny modified the milestones: 1.1.0, 1.2.0 Feb 9, 2017
@andrew-boyarshin
Copy link
Contributor Author

andrew-boyarshin commented Feb 10, 2017

I've finally figured out the correct API code, it was different from both old code and my change. Fixed, added tests to the API (looks like noone ever did API tests in Gogs/Gitea before me). Also increased code coverage, added a couple of tests. Finally, it is completely ready (or at least I hope so).
@lunny LGTM is still in operation?

Uhm... Drone is unable to find new code.gitea.io/gitea/routers/api/v1/misc tests. Works fine for me. File is pushed. What is going on?

@andrew-boyarshin
Copy link
Contributor Author

Anyone willing to review?

@strk
Copy link
Member

strk commented Feb 11, 2017 via email

@andrew-boyarshin
Copy link
Contributor Author

andrew-boyarshin commented Feb 11, 2017

@strk you mean good repos to test on? I test it on guard, libgdx, jquery, D3 wikis. There are also some screenshots in the original Gogs version of this PR.

@andrew-boyarshin
Copy link
Contributor Author

There are also tests in this PR, which cover everything pretty good (if not to count API tests, which only work locally; strange thing, haven't figured out why it didn't work remotely).

@andrew-boyarshin
Copy link
Contributor Author

andrew-boyarshin commented Feb 11, 2017

OK, 1 out of 2 LGTMs, two approved reviews. Final LGTM and good to go?

@andrew-boyarshin
Copy link
Contributor Author

Anyone willing to review?

@andreynering
Copy link
Contributor

LGTM

I'll let the owners decide, but I'd merge right this after the v1.1 release, so people that use master may file any bugs that may happen until we have this in a stable release (v1.2).

@tboerger tboerger added lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. and removed lgtm/need 1 This PR needs approval from one additional maintainer to be merged. labels Feb 13, 2017
@lunny lunny merged commit dc8248f into go-gitea:master Feb 14, 2017
@lunny
Copy link
Member

lunny commented Feb 14, 2017

@andreynering that's a good idea. We need a PR to stay on master for a long time to find more bugs. I'm thinking our release cycle. Maybe we should publish a release about 2 months? 1 month for merge new feature, one month for bug fixed. All the PRs on the second month should be merged at next release cycle.

@andrew-boyarshin andrew-boyarshin deleted the markdownPR branch February 14, 2017 06:04
@Lourens-Rich
Copy link

Lourens-Rich commented Feb 18, 2017

Sorry, i want to ask about my problem with markdown texts.
https://git.r208.tk/Lourens-Rich/Education/src/master/Readme.md
On this link we can see how a table looks uncorrected (Headers are misplaced). This worked normally before.

@andrew-boyarshin
Copy link
Contributor Author

andrew-boyarshin commented Feb 19, 2017

@Lourens-Rich it should be unrelated to this PR. Yet, I confirm the problem and the solution is to remove display: block from table, that is _markdown.less#L243. It solves the problem, although it makes table 100% wide in parent container (nothing can be to the left or right side of the table anyway).

text = append([]byte(`<div class="ui checked fitted disabled checkbox"><input type="checkbox" checked="" disabled="disabled" /><label /></div>`), text[3+len(prefix):]...)
}
if prefix != "" {
text = bytes.Replace(text, []byte("</p>"), []byte{}, 1)
Copy link
Member

@Morlinest Morlinest Apr 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andrew-boyarshin You should remove "/p" tag only if you also remove starting tag (so only if u do append). This code cause bugs in rendering (example: a list rendering bug with code in list - "/li" is replaced by "/p" in postprocess because the last starting tag before "pre, code" is only starting "p" tag).

@pree pree mentioned this pull request Apr 27, 2017
7 tasks
@go-gitea go-gitea locked and limited conversation to collaborators Nov 23, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. type/enhancement An improvement of existing functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.