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

Use markdown frontmatter to provide Table of contents, language and frontmatter rendering #11047

Merged
merged 18 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Add language control for TOC
Signed-off-by: Andrew Thornton <[email protected]>
  • Loading branch information
zeripath committed Apr 12, 2020
commit 67ff9011536fe5d97869225de6f24b52fe41ad21
44 changes: 41 additions & 3 deletions modules/markup/markdown/goldmark.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/common"
"code.gitea.io/gitea/modules/setting"
giteautil "code.gitea.io/gitea/modules/util"

meta "github.com/yuin/goldmark-meta"
Expand Down Expand Up @@ -43,9 +44,13 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
firstChild := node.FirstChild()
createTOC := false
var toc = []Header{}
rc := &RenderConfig{
Meta: "table",
Icon: "table",
Lang: "",
}
if metaData != nil {
rc := ToRenderConfig(metaData)
log.Info("%v", rc)
rc.ToRenderConfig(metaData)

metaNode := rc.toMetaNode(metaData)
if metaNode != nil {
Expand Down Expand Up @@ -131,11 +136,19 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
})

if createTOC && len(toc) > 0 {
tocNode := createTOCNode(toc)
lang := rc.Lang
if len(lang) == 0 {
lang = setting.Langs[0]
}
tocNode := createTOCNode(toc, rc.Lang)
if tocNode != nil {
node.InsertBefore(node, firstChild, tocNode)
}
}

if len(rc.Lang) > 0 {
node.SetAttributeString("lang", []byte(rc.Lang))
}
}

type prefixedIDs struct {
Expand Down Expand Up @@ -204,12 +217,37 @@ type HTMLRenderer struct {

// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
func (r *HTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
reg.Register(ast.KindDocument, r.renderDocument)
reg.Register(KindDetails, r.renderDetails)
reg.Register(KindSummary, r.renderSummary)
reg.Register(KindIcon, r.renderIcon)
reg.Register(east.KindTaskCheckBox, r.renderTaskCheckBox)
}

func (r *HTMLRenderer) renderDocument(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
log.Info("renderDocument %v", node)
n := node.(*ast.Document)

var err error
if entering {
_, err = w.WriteString("<div")
if val, has := n.AttributeString("lang"); has && err == nil {
_, err = w.WriteString(fmt.Sprintf(` lang=%q`, val))
}
if err == nil {
_, err = w.WriteRune('>')
}
} else {
_, err = w.WriteString("</div>")
}

if err != nil {
return ast.WalkStop, err
}

return ast.WalkContinue, nil
}

func (r *HTMLRenderer) renderDetails(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
var err error
if entering {
Expand Down
5 changes: 2 additions & 3 deletions modules/markup/markdown/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
parser.WithAttribute(),
parser.WithAutoHeadingID(),
parser.WithASTTransformers(
util.Prioritized(&GiteaASTTransformer{}, 10000),
util.Prioritized(&ASTTransformer{}, 10000),
),
),
goldmark.WithRendererOptions(
Expand All @@ -71,7 +71,7 @@ func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
// Override the original Tasklist renderer!
converter.Renderer().AddOptions(
renderer.WithNodeRenderers(
util.Prioritized(NewHTMLRenderer(), 1000),
util.Prioritized(NewHTMLRenderer(), 10),
),
)

Expand All @@ -85,7 +85,6 @@ func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
if err := converter.Convert(giteautil.NormalizeEOL(body), &buf, parser.WithContext(pc)); err != nil {
log.Error("Unable to render: %v", err)
}

return markup.SanitizeReader(&buf).Bytes()
}

Expand Down
47 changes: 33 additions & 14 deletions modules/markup/markdown/renderconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,16 @@ type RenderConfig struct {
Meta string
Icon string
TOC bool
Lang string
}

// ToRenderConfig converts a yaml.MapSlice to a RenderConfig
func ToRenderConfig(meta yaml.MapSlice) *RenderConfig {
rc := &RenderConfig{
Meta: "table",
Icon: "table",
}
func (rc *RenderConfig) ToRenderConfig(meta yaml.MapSlice) {
if meta == nil {
return rc
return
}
var giteaMetaControl *yaml.MapItem
found := false
var giteaMetaControl yaml.MapItem
for _, item := range meta {
strKey, ok := item.Key.(string)
if !ok {
Expand All @@ -38,17 +36,28 @@ func ToRenderConfig(meta yaml.MapSlice) *RenderConfig {
strKey = strings.TrimSpace(strings.ToLower(strKey))
switch strKey {
case "gitea":
giteaMetaControl = &item
giteaMetaControl = item
found = true
case "include_toc":
val, ok := item.Value.(bool)
if !ok {
continue
}
rc.TOC = val
case "lang":
val, ok := item.Value.(string)
if !ok {
continue
}
val = strings.TrimSpace(val)
if len(val) == 0 {
continue
}
rc.Lang = val
}
}

if giteaMetaControl != nil {
if found {
switch v := giteaMetaControl.Value.(type) {
case string:
switch v {
Expand All @@ -68,14 +77,13 @@ func ToRenderConfig(meta yaml.MapSlice) *RenderConfig {
continue
}
strKey = strings.TrimSpace(strings.ToLower(strKey))
strValue, ok := item.Value.(string)
strValue = strings.TrimSpace(strings.ToLower(strValue))
switch strKey {
case "meta":
val, ok := item.Value.(string)
if !ok {
continue
}
switch strValue {
switch strings.TrimSpace(strings.ToLower(val)) {
case "none":
rc.Meta = "none"
case "table":
Expand All @@ -86,21 +94,32 @@ func ToRenderConfig(meta yaml.MapSlice) *RenderConfig {
rc.Meta = "details"
}
case "details_icon":
val, ok := item.Value.(string)
if !ok {
continue
}
rc.Icon = strValue
rc.Icon = strings.TrimSpace(strings.ToLower(val))
case "include_toc":
val, ok := item.Value.(bool)
if !ok {
continue
}
rc.TOC = val
case "lang":
val, ok := item.Value.(string)
if !ok {
continue
}
val = strings.TrimSpace(val)
if len(val) == 0 {
continue
}
rc.Lang = val
}
}
}
}
return rc
return
}

func (rc *RenderConfig) toMetaNode(meta yaml.MapSlice) ast.Node {
Expand Down
6 changes: 4 additions & 2 deletions modules/markup/markdown/toc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import (
"fmt"
"net/url"

"github.com/unknwon/i18n"
"github.com/yuin/goldmark/ast"
)

func createTOCNode(toc []Header) ast.Node {
func createTOCNode(toc []Header, lang string) ast.Node {
details := NewDetails()
summary := NewSummary()
summary.AppendChild(summary, ast.NewString([]byte("Table of Contents")))

summary.AppendChild(summary, ast.NewString([]byte(i18n.Tr(lang, "toc"))))
details.AppendChild(details, summary)
ul := ast.NewList('-')
details.AppendChild(details, ul)
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ create_new = Create…
user_profile_and_more = Profile and Settings…
signed_in_as = Signed in as
enable_javascript = This website works better with JavaScript.
toc = Table of Contents

username = Username
email = Email Address
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_es-ES.ini
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ create_new=Crear…
user_profile_and_more=Perfil y ajustes…
signed_in_as=Identificado como
enable_javascript=Este sitio web funciona mejor con JavaScript.
toc=Tabla de contenido
zeripath marked this conversation as resolved.
Show resolved Hide resolved

username=Nombre de usuario
email=Correo electrónico
Expand Down