]> source.dussan.org Git - gitea.git/commitdiff
Allow different HardBreaks settings for documents and comments (#11515) (#11599)
authorzeripath <art27@cantab.net>
Sun, 24 May 2020 10:45:56 +0000 (11:45 +0100)
committerGitHub <noreply@github.com>
Sun, 24 May 2020 10:45:56 +0000 (11:45 +0100)
GH has different HardBreaks behaviour for markdown comments and documents.

Comments have hard breaks and documents have soft breaks - therefore Gitea's rendering will always be different from GH's if we only provide one setting.

Here we split the setting in to two - one for documents and one for comments and other things.

Signed-off-by: Andrew Thornton art27@cantab.net
Changes to index.js as per @silverwind
Co-authored-by: silverwind <me@silverwind.io>
Changes to docs as per @guillep2k
Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>
12 files changed:
custom/conf/app.ini.sample
docs/content/doc/advanced/config-cheat-sheet.en-us.md
models/repo.go
modules/markup/markdown/goldmark.go
modules/markup/markdown/markdown.go
modules/setting/setting.go
routers/api/v1/misc/markdown.go
routers/api/v1/misc/markdown_test.go
routers/repo/view.go
routers/repo/wiki.go
templates/repo/editor/edit.tmpl
web_src/js/index.js

index c8797ca56a72bcf75a9c944e44e0c0ff57e4ef40..c50dd68f1f59d0d89265362b3de2c2b5eb823944 100644 (file)
@@ -216,7 +216,10 @@ EVENT_SOURCE_UPDATE_TIME = 10s
 ; Render soft line breaks as hard line breaks, which means a single newline character between
 ; paragraphs will cause a line break and adding trailing whitespace to paragraphs is not
 ; necessary to force a line break.
-ENABLE_HARD_LINE_BREAK = true
+; Render soft line breaks as hard line breaks for comments
+ENABLE_HARD_LINE_BREAK_IN_COMMENTS = true
+; Render soft line breaks as hard line breaks for markdown documents
+ENABLE_HARD_LINE_BREAK_IN_DOCUMENTS = false
 ; Comma separated list of custom URL-Schemes that are allowed as links when rendering Markdown
 ; for example git,magnet,ftp (more at https://en.wikipedia.org/wiki/List_of_URI_schemes)
 ; URLs starting with http and https are always displayed, whatever is put in this entry.
index 3ad24776ff2815158b29eab207996f1f5eacd1d1..e3ff2deb37df7a15b27ed48953dbcee27662c92d 100644 (file)
@@ -152,7 +152,10 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
 
 ## Markdown (`markdown`)
 
-- `ENABLE_HARD_LINE_BREAK`: **true**: Render soft line breaks as hard line breaks, which
+- `ENABLE_HARD_LINE_BREAK_IN_COMMENTS`: **true**: Render soft line breaks as hard line breaks in comments, which
+  means a single newline character between paragraphs will cause a line break and adding
+  trailing whitespace to paragraphs is not necessary to force a line break.
+- `ENABLE_HARD_LINE_BREAK_IN_DOCUMENTS`: **false**: Render soft line breaks as hard line breaks in documents, which
   means a single newline character between paragraphs will cause a line break and adding
   trailing whitespace to paragraphs is not necessary to force a line break.
 - `CUSTOM_URL_SCHEMES`: Use a comma separated list (ftp,git,svn) to indicate additional
index f79740e747588bce9f734c19eea9def9fd24e345..13830c67f08859689c107b0b5c4e4744ca9a82ee 100644 (file)
@@ -174,9 +174,10 @@ type Repository struct {
        *Mirror    `xorm:"-"`
        Status     RepositoryStatus `xorm:"NOT NULL DEFAULT 0"`
 
-       RenderingMetas  map[string]string `xorm:"-"`
-       Units           []*RepoUnit       `xorm:"-"`
-       PrimaryLanguage *LanguageStat     `xorm:"-"`
+       RenderingMetas         map[string]string `xorm:"-"`
+       DocumentRenderingMetas map[string]string `xorm:"-"`
+       Units                  []*RepoUnit       `xorm:"-"`
+       PrimaryLanguage        *LanguageStat     `xorm:"-"`
 
        IsFork                          bool               `xorm:"INDEX NOT NULL DEFAULT false"`
        ForkID                          int64              `xorm:"INDEX"`
@@ -534,11 +535,12 @@ func (repo *Repository) mustOwner(e Engine) *User {
 
 // ComposeMetas composes a map of metas for properly rendering issue links and external issue trackers.
 func (repo *Repository) ComposeMetas() map[string]string {
-       if repo.RenderingMetas == nil {
+       if len(repo.RenderingMetas) == 0 {
                metas := map[string]string{
                        "user":     repo.OwnerName,
                        "repo":     repo.Name,
                        "repoPath": repo.RepoPath(),
+                       "mode":     "comment",
                }
 
                unit, err := repo.GetUnit(UnitTypeExternalTracker)
@@ -570,6 +572,19 @@ func (repo *Repository) ComposeMetas() map[string]string {
        return repo.RenderingMetas
 }
 
+// ComposeDocumentMetas composes a map of metas for properly rendering documents
+func (repo *Repository) ComposeDocumentMetas() map[string]string {
+       if len(repo.DocumentRenderingMetas) == 0 {
+               metas := map[string]string{}
+               for k, v := range repo.ComposeMetas() {
+                       metas[k] = v
+               }
+               metas["mode"] = "document"
+               repo.DocumentRenderingMetas = metas
+       }
+       return repo.DocumentRenderingMetas
+}
+
 // DeleteWiki removes the actual and local copy of repository wiki.
 func (repo *Repository) DeleteWiki() error {
        return repo.deleteWiki(x)
index bf02a22d5e163e6ae05939a84337ed9a53ff7195..9447424644f001097f1c2cd874df36cfcfae9412 100644 (file)
@@ -151,6 +151,16 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
                                        v.AppendChild(v, newChild)
                                }
                        }
+               case *ast.Text:
+                       if v.SoftLineBreak() && !v.HardLineBreak() {
+                               renderMetas := pc.Get(renderMetasKey).(map[string]string)
+                               mode := renderMetas["mode"]
+                               if mode != "document" {
+                                       v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInComments)
+                               } else {
+                                       v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInDocuments)
+                               }
+                       }
                }
                return ast.WalkContinue, nil
        })
index e50301ffe4a04be1b96927a0257548d8cf030858..515d6846868b177a688655914c547d4e45286569 100644 (file)
@@ -29,17 +29,19 @@ var once = sync.Once{}
 
 var urlPrefixKey = parser.NewContextKey()
 var isWikiKey = parser.NewContextKey()
+var renderMetasKey = parser.NewContextKey()
 
 // NewGiteaParseContext creates a parser.Context with the gitea context set
-func NewGiteaParseContext(urlPrefix string, isWiki bool) parser.Context {
+func NewGiteaParseContext(urlPrefix string, metas map[string]string, isWiki bool) parser.Context {
        pc := parser.NewContext(parser.WithIDs(newPrefixedIDs()))
        pc.Set(urlPrefixKey, urlPrefix)
        pc.Set(isWikiKey, isWiki)
+       pc.Set(renderMetasKey, metas)
        return pc
 }
 
-// RenderRaw renders Markdown to HTML without handling special links.
-func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
+// render renders Markdown to HTML without handling special links.
+func render(body []byte, urlPrefix string, metas map[string]string, wikiMarkdown bool) []byte {
        once.Do(func() {
                converter = goldmark.New(
                        goldmark.WithExtensions(extension.Table,
@@ -75,12 +77,9 @@ func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
                        ),
                )
 
-               if setting.Markdown.EnableHardLineBreak {
-                       converter.Renderer().AddOptions(html.WithHardWraps())
-               }
        })
 
-       pc := NewGiteaParseContext(urlPrefix, wikiMarkdown)
+       pc := NewGiteaParseContext(urlPrefix, metas, wikiMarkdown)
        var buf bytes.Buffer
        if err := converter.Convert(giteautil.NormalizeEOL(body), &buf, parser.WithContext(pc)); err != nil {
                log.Error("Unable to render: %v", err)
@@ -112,7 +111,7 @@ func (Parser) Extensions() []string {
 
 // Render implements markup.Parser
 func (Parser) Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte {
-       return RenderRaw(rawBytes, urlPrefix, isWiki)
+       return render(rawBytes, urlPrefix, metas, isWiki)
 }
 
 // Render renders Markdown to HTML with all specific handling stuff.
@@ -120,6 +119,11 @@ func Render(rawBytes []byte, urlPrefix string, metas map[string]string) []byte {
        return markup.Render("a.md", rawBytes, urlPrefix, metas)
 }
 
+// RenderRaw renders Markdown to HTML without handling special links.
+func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
+       return render(body, urlPrefix, map[string]string{}, wikiMarkdown)
+}
+
 // RenderString renders Markdown to HTML with special links and returns string type.
 func RenderString(raw, urlPrefix string, metas map[string]string) string {
        return markup.RenderString("a.md", raw, urlPrefix, metas)
index 9507d4693084d21a1a59ae52fe933b317d76416a..b8ec957535059454cf7b7a91e6455cfef994638f 100644 (file)
@@ -256,12 +256,14 @@ var (
 
        // Markdown settings
        Markdown = struct {
-               EnableHardLineBreak bool
-               CustomURLSchemes    []string `ini:"CUSTOM_URL_SCHEMES"`
-               FileExtensions      []string
+               EnableHardLineBreakInComments  bool
+               EnableHardLineBreakInDocuments bool
+               CustomURLSchemes               []string `ini:"CUSTOM_URL_SCHEMES"`
+               FileExtensions                 []string
        }{
-               EnableHardLineBreak: true,
-               FileExtensions:      strings.Split(".md,.markdown,.mdown,.mkd", ","),
+               EnableHardLineBreakInComments:  true,
+               EnableHardLineBreakInDocuments: false,
+               FileExtensions:                 strings.Split(".md,.markdown,.mdown,.mkd", ","),
        }
 
        // Admin settings
index 5a44db5e8bccd91a765f090d5740c48f62771808..a10c288df482f7b4dfe1140b408dc97eec5fc877 100644 (file)
@@ -48,10 +48,12 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) {
        }
 
        switch form.Mode {
+       case "comment":
+               fallthrough
        case "gfm":
                md := []byte(form.Text)
                urlPrefix := form.Context
-               var meta map[string]string
+               meta := map[string]string{}
                if !strings.HasPrefix(setting.AppSubURL+"/", urlPrefix) {
                        // check if urlPrefix is already set to a URL
                        linkRegex, _ := xurls.StrictMatchingScheme("https?://")
@@ -61,7 +63,15 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) {
                        }
                }
                if ctx.Repo != nil && ctx.Repo.Repository != nil {
-                       meta = ctx.Repo.Repository.ComposeMetas()
+                       // "gfm" = Github Flavored Markdown - set this to render as a document
+                       if form.Mode == "gfm" {
+                               meta = ctx.Repo.Repository.ComposeDocumentMetas()
+                       } else {
+                               meta = ctx.Repo.Repository.ComposeMetas()
+                       }
+               }
+               if form.Mode == "gfm" {
+                       meta["mode"] = "document"
                }
                if form.Wiki {
                        _, err := ctx.Write([]byte(markdown.RenderWiki(md, urlPrefix, meta)))
index 264a6010f972786087f81011b229ee03c9810ad1..6c81ec8eb4357060b31619629e6569e686ed7d25 100644 (file)
@@ -94,7 +94,7 @@ Here are some links to the most important topics. You can find the full list of
 <p><strong>Wine Staging</strong> on website <a href="http://wine-staging.com" rel="nofollow">wine-staging.com</a>.</p>
 <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>
-<p><a href="` + AppSubURL + `wiki/Configuration" rel="nofollow">Configuration</a><br/>
+<p><a href="` + AppSubURL + `wiki/Configuration" rel="nofollow">Configuration</a>
 <a href="` + AppSubURL + `wiki/raw/images/icon-bug.png" rel="nofollow"><img src="` + AppSubURL + `wiki/raw/images/icon-bug.png" title="icon-bug.png" alt="images/icon-bug.png"/></a></p>
 `,
                // Guard wiki sidebar: special syntax
index 9c9cdc06bfe74d801ca2e7acba1f4dbd7afe6a79..0f4e2d838cfbf70fc829ceedd2b1dbc4c4061201 100644 (file)
@@ -319,7 +319,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
                                if markupType := markup.Type(readmeFile.name); markupType != "" {
                                        ctx.Data["IsMarkup"] = true
                                        ctx.Data["MarkupType"] = string(markupType)
-                                       ctx.Data["FileContent"] = string(markup.Render(readmeFile.name, buf, readmeTreelink, ctx.Repo.Repository.ComposeMetas()))
+                                       ctx.Data["FileContent"] = string(markup.Render(readmeFile.name, buf, readmeTreelink, ctx.Repo.Repository.ComposeDocumentMetas()))
                                } else {
                                        ctx.Data["IsRenderedHTML"] = true
                                        ctx.Data["FileContent"] = strings.Replace(
@@ -459,7 +459,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
                if markupType := markup.Type(blob.Name()); markupType != "" {
                        ctx.Data["IsMarkup"] = true
                        ctx.Data["MarkupType"] = markupType
-                       ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas()))
+                       ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeDocumentMetas()))
                } else if readmeExist {
                        ctx.Data["IsRenderedHTML"] = true
                        ctx.Data["FileContent"] = strings.Replace(
@@ -538,7 +538,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
                        buf = append(buf, d...)
                        ctx.Data["IsMarkup"] = true
                        ctx.Data["MarkupType"] = markupType
-                       ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas()))
+                       ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeDocumentMetas()))
                }
 
        }
index 5da01f21acf38e7d315b0c9009ce83909d0ddf97..29b0fb2ea6093efdf6ba997813adac1b55c09f37 100644 (file)
@@ -209,7 +209,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
                return nil, nil
        }
 
-       metas := ctx.Repo.Repository.ComposeMetas()
+       metas := ctx.Repo.Repository.ComposeDocumentMetas()
        ctx.Data["content"] = markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
        ctx.Data["sidebarPresent"] = sidebarContent != nil
        ctx.Data["sidebarContent"] = markdown.RenderWiki(sidebarContent, ctx.Repo.RepoLink, metas)
index 283bd3250863948a72b21602310cdc80c3e87ede..cc98539eabe0a5e57cb8a2b1b159e8cc6a8b2e07 100644 (file)
@@ -30,7 +30,7 @@
                                <div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
                                        <a class="active item" data-tab="write">{{svg "octicon-code" 16}} {{if .IsNewFile}}{{.i18n.Tr "repo.editor.new_file"}}{{else}}{{.i18n.Tr "repo.editor.edit_file"}}{{end}}</a>
                                        {{if not .IsNewFile}}
-                                       <a class="item" data-tab="preview" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}">{{svg "octicon-eye" 16}} {{.i18n.Tr "preview"}}</a>
+                                       <a class="item" data-tab="preview" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}" data-markdown-mode="gfm">{{svg "octicon-eye" 16}} {{.i18n.Tr "preview"}}</a>
                                        <a class="item" data-tab="diff" data-url="{{.RepoLink}}/_preview/{{.BranchName | EscapePound}}/{{.TreePath | EscapePound}}" data-context="{{.BranchLink}}">{{svg "octicon-diff" 16}} {{.i18n.Tr "repo.editor.preview_changes"}}</a>
                                        {{end}}
                                </div>
index 9aab32faab4c9e32f162cbd05f36f6fada3b1c6f..60ce8042c0ea1884e0838cadb1b82a86d3f1f216 100644 (file)
@@ -42,7 +42,7 @@ function initCommentPreviewTab($form) {
     const $this = $(this);
     $.post($this.data('url'), {
       _csrf: csrf,
-      mode: 'gfm',
+      mode: 'comment',
       context: $this.data('context'),
       text: $form.find(`.tab[data-tab="${$tabMenu.data('write')}"] textarea`).val()
     }, (data) => {
@@ -66,6 +66,7 @@ function initEditPreviewTab($form) {
     $previewTab.on('click', function () {
       const $this = $(this);
       let context = `${$this.data('context')}/`;
+      const mode = $this.data('markdown-mode') || 'comment';
       const treePathEl = $form.find('input#tree_path');
       if (treePathEl.length > 0) {
         context += treePathEl.val();
@@ -73,7 +74,7 @@ function initEditPreviewTab($form) {
       context = context.substring(0, context.lastIndexOf('/'));
       $.post($this.data('url'), {
         _csrf: csrf,
-        mode: 'gfm',
+        mode,
         context,
         text: $form.find(`.tab[data-tab="${$tabMenu.data('write')}"] textarea`).val()
       }, (data) => {