]> source.dussan.org Git - gitea.git/commitdiff
Markdown task list improvements (#13952)
authorsilverwind <me@silverwind.io>
Sun, 13 Dec 2020 01:05:50 +0000 (02:05 +0100)
committerGitHub <noreply@github.com>
Sun, 13 Dec 2020 01:05:50 +0000 (09:05 +0800)
* Markdown task list improvements

- Remove `.ui` class and wrappers to prevent fomantic from messing with it.
- Change rendered HTML to match GitHub.
- Add custom styling for the checkboxes.

* fix unittest

Co-authored-by: Lauris BH <lauris@nix.lv>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
modules/markup/markdown/goldmark.go
modules/markup/markdown/markdown_test.go
modules/markup/sanitizer.go
modules/markup/sanitizer_test.go
web_src/less/_markdown.less

index 9447424644f001097f1c2cd874df36cfcfae9412..f9fd6eb9764bba904592f8c15d44b9a4ff698123 100644 (file)
@@ -357,9 +357,9 @@ func (r *HTMLRenderer) renderTaskCheckBoxListItem(w util.BufWriter, source []byt
                }
                var err error
                if n.IsChecked {
-                       _, err = w.WriteString(`<span class="ui checked checkbox"><input type="checkbox" checked="" readonly="readonly"` + end + `<label>`)
+                       _, err = w.WriteString(`<input type="checkbox" disabled="" checked=""` + end)
                } else {
-                       _, err = w.WriteString(`<span class="ui checkbox"><input type="checkbox" readonly="readonly"` + end + `<label>`)
+                       _, err = w.WriteString(`<input type="checkbox" disabled=""` + end)
                }
                if err != nil {
                        return ast.WalkStop, err
@@ -371,7 +371,7 @@ func (r *HTMLRenderer) renderTaskCheckBoxListItem(w util.BufWriter, source []byt
                        }
                }
        } else {
-               _, _ = w.WriteString("</label></span></li>\n")
+               _, _ = w.WriteString("</li>\n")
        }
        return ast.WalkContinue, nil
 }
index 7f27a43a7d9714d188a2496f4da51453d097caa8..89005fc25d8e439a2aba10bc9645ea1f5bf40398 100644 (file)
@@ -142,9 +142,9 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
 <p>(from <a href="https://www.markdownguide.org/extended-syntax/" rel="nofollow">https://www.markdownguide.org/extended-syntax/</a>)</p>
 <h3 id="user-content-checkboxes">Checkboxes</h3>
 <ul>
-<li class="task-list-item"><span class="ui checkbox"><input type="checkbox" readonly="readonly"/><label>unchecked</label></span></li>
-<li class="task-list-item"><span class="ui checked checkbox"><input type="checkbox" checked="" readonly="readonly"/><label>checked</label></span></li>
-<li class="task-list-item"><span class="ui checkbox"><input type="checkbox" readonly="readonly"/><label>still unchecked</label></span></li>
+<li class="task-list-item"><input type="checkbox" disabled=""/>unchecked</li>
+<li class="task-list-item"><input type="checkbox" disabled="" checked=""/>checked</li>
+<li class="task-list-item"><input type="checkbox" disabled=""/>still unchecked</li>
 </ul>
 <h3 id="user-content-definition-list">Definition list</h3>
 <dl>
index ba73650bdfcb40edc8326f94613628a9ef7d5865..9214a75fb355b574b2898da2380ec7822e11c34d 100644 (file)
@@ -43,7 +43,7 @@ func ReplaceSanitizer() {
 
        // Checkboxes
        sanitizer.policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
-       sanitizer.policy.AllowAttrs("checked", "disabled", "readonly").OnElements("input")
+       sanitizer.policy.AllowAttrs("checked", "disabled").OnElements("input")
 
        // Custom URL-Schemes
        sanitizer.policy.AllowURLSchemes(setting.Markdown.CustomURLSchemes...)
@@ -66,8 +66,8 @@ func ReplaceSanitizer() {
        // Allow classes for emojis
        sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`emoji`)).OnElements("img")
 
-       // Allow icons, checkboxes, emojis, and chroma syntax on span
-       sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^((icon(\s+[\p{L}\p{N}_-]+)+)|(ui checkbox)|(ui checked checkbox)|(emoji))$|^([a-z][a-z0-9]{0,2})$`)).OnElements("span")
+       // Allow icons, emojis, and chroma syntax on span
+       sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^((icon(\s+[\p{L}\p{N}_-]+)+)|(emoji))$|^([a-z][a-z0-9]{0,2})$`)).OnElements("span")
 
        // Allow generally safe attributes
        generalSafeAttrs := []string{"abbr", "accept", "accept-charset",
index 3e8dcecd50eb617f945fb6bff3e5fc20e68464e1..63b70166d830f4b5d0ff7ebc5013ba94b62e2a04 100644 (file)
@@ -40,7 +40,7 @@ func Test_Sanitizer(t *testing.T) {
                `<kbd>Ctrl + C</kbd>`, `<kbd>Ctrl + C</kbd>`,
                `<i class="dropdown icon">NAUGHTY</i>`, `<i>NAUGHTY</i>`,
                `<i class="icon dropdown"></i>`, `<i class="icon dropdown"></i>`,
-               `<span class="ui checkbox"><input type="checkbox" readonly="readonly"/><label>unchecked</label></span>`, `<span class="ui checkbox"><input type="checkbox" readonly="readonly"/><label>unchecked</label></span>`,
+               `<input type="checkbox" disabled=""/>unchecked`, `<input type="checkbox" disabled=""/>unchecked`,
                `<span class="emoji dropdown">NAUGHTY</span>`, `<span>NAUGHTY</span>`,
                `<span class="emoji">contents</span>`, `<span class="emoji">contents</span>`,
        }
index 4c8ed77cb8c0f59cea7dd123aa134249ae98cdbe..f931106d9504a2a660b7e38041171feece41054c 100644 (file)
     list-style-type: none;
   }
 
-  li.task-list-item {
+  .task-list-item {
     list-style-type: none;
-    margin-left: calc(-2em + 2px);
+
+    input[type="checkbox"] {
+      margin: 0 6px .25em -1.6em;
+    }
+  }
+
+  .task-list-item + .task-list-item {
+    margin-top: 3px;
+  }
+
+  input[type="checkbox"] {
+    -webkit-appearance: none;
+    -moz-appearance: none;
+    appearance: none;
+    position: relative;
+    border: 1px solid var(--color-secondary);
+    border-radius: 2px;
+    background: var(--color-input-background);
+    height: 14px;
+    width: 14px;
+    opacity: 1 !important; // override fomantic on edit preview
+    pointer-events: auto !important; // override fomantic on edit preview
+    vertical-align: middle !important; // override fomantic on edit preview
+  }
+
+  input[type="checkbox"]:not([disabled]):hover,
+  input[type="checkbox"]:not([disabled]):active {
+    border-color: var(--color-primary);
+  }
+
+  input[type="checkbox"]::after {
+    position: absolute;
+    left: 0;
+    top: 0;
+    bottom: 0;
+    right: 0;
+    pointer-events: none;
+    background: var(--color-text);
+    mask-size: cover;
+  }
+
+  input[type="checkbox"]:checked::after {
+    content: "";
+    mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 18 18" width="16" height="16"><path fill-rule="evenodd" d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"></path></svg>');
+  }
+
+  input[type="checkbox"]:indeterminate::after {
+    content: "";
+    mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2 7.75A.75.75 0 012.75 7h10a.75.75 0 010 1.5h-10A.75.75 0 012 7.75z"></path></svg>');
   }
 
   ul ul,
     box-shadow: inset 0 -1px 0 var(--color-secondary);
   }
 
-  input[type="checkbox"] {
-    vertical-align: middle !important;
-  }
-
   .csv-data td,
   .csv-data th {
     padding: 5px;