From f62cd2f4738c1b3cf7c31e8b98702a709bdd4072 Mon Sep 17 00:00:00 2001 From: Jonathan Tran Date: Tue, 13 Jun 2023 02:44:47 -0400 Subject: Fix task list checkbox toggle to work with YAML front matter (#25184) Fixes #25160. `data-source-position` of checkboxes in a task list was incorrect whenever there was YAML front matter. This would result in issue content or PR descriptions getting corrupted with random `x` or space characters when a user checked or unchecked a task. --- modules/markup/markdown/ast.go | 4 +++- modules/markup/markdown/goldmark.go | 12 +++++------ modules/markup/markdown/markdown.go | 9 ++++++++ modules/markup/markdown/markdown_test.go | 37 ++++++++++++++++++++++++++++++++ modules/markup/markdown/renderconfig.go | 3 +++ 5 files changed, 58 insertions(+), 7 deletions(-) (limited to 'modules/markup') diff --git a/modules/markup/markdown/ast.go b/modules/markup/markdown/ast.go index e844f801c4..3e6e291ab2 100644 --- a/modules/markup/markdown/ast.go +++ b/modules/markup/markdown/ast.go @@ -76,7 +76,8 @@ func IsSummary(node ast.Node) bool { // TaskCheckBoxListItem is a block that represents a list item of a markdown block with a checkbox type TaskCheckBoxListItem struct { *ast.ListItem - IsChecked bool + IsChecked bool + SourcePosition int } // KindTaskCheckBoxListItem is the NodeKind for TaskCheckBoxListItem @@ -86,6 +87,7 @@ var KindTaskCheckBoxListItem = ast.NewNodeKind("TaskCheckBoxListItem") func (n *TaskCheckBoxListItem) Dump(source []byte, level int) { m := map[string]string{} m["IsChecked"] = strconv.FormatBool(n.IsChecked) + m["SourcePosition"] = strconv.FormatInt(int64(n.SourcePosition), 10) ast.DumpHelper(n, source, level, m, nil) } diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index f03a780900..ff4e6b1bd0 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -177,6 +177,11 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa newChild := NewTaskCheckBoxListItem(listItem) newChild.IsChecked = taskCheckBox.IsChecked newChild.SetAttributeString("class", []byte("task-list-item")) + segments := newChild.FirstChild().Lines() + if segments.Len() > 0 { + segment := segments.At(0) + newChild.SourcePosition = rc.metaLength + segment.Start + } v.AppendChild(v, newChild) } } @@ -457,12 +462,7 @@ func (r *HTMLRenderer) renderTaskCheckBoxListItem(w util.BufWriter, source []byt } else { _, _ = w.WriteString("
  • ") } - _, _ = w.WriteString(` 0 { - segment := segments.At(0) - _, _ = w.WriteString(fmt.Sprintf(` data-source-position="%d"`, segment.Start)) - } + fmt.Fprintf(w, ` + + + + + + + + + + +
    foo
    bar
    + +`, + }, + } + + for _, test := range testcases { + res, err := RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) + assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) + assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase) + } +} diff --git a/modules/markup/markdown/renderconfig.go b/modules/markup/markdown/renderconfig.go index 691df74312..f4c48d1b3d 100644 --- a/modules/markup/markdown/renderconfig.go +++ b/modules/markup/markdown/renderconfig.go @@ -20,6 +20,9 @@ type RenderConfig struct { TOC string // "false": hide, "side"/empty: in sidebar, "main"/"true": in main view Lang string yamlNode *yaml.Node + + // Used internally. Cannot be controlled by frontmatter. + metaLength int } func renderMetaModeFromString(s string) markup.RenderMetaMode { -- cgit v1.2.3