forgejo/modules/markup/markdown/callout/github_legacy.go
Yaroslav Halchenko 2b2fd2728c Add codespell support and fix a good number of typos with its help (#3270)
More about codespell: https://github.com/codespell-project/codespell .

I personally introduced it to dozens if not hundreds of projects already and so far only positive feedback.

```
❯ grep lint-spell Makefile
	@echo " - lint-spell                       lint spelling"
	@echo " - lint-spell-fix                   lint spelling and fix issues"
lint: lint-frontend lint-backend lint-spell
lint-fix: lint-frontend-fix lint-backend-fix lint-spell-fix
.PHONY: lint-spell
lint-spell: lint-codespell
.PHONY: lint-spell-fix
lint-spell-fix: lint-codespell-fix
❯ git grep lint- -- .forgejo/
.forgejo/workflows/testing.yml:      - run: make --always-make -j$(nproc) lint-backend checks-backend # ensure the "go-licenses" make target runs
.forgejo/workflows/testing.yml:      - run: make lint-frontend
```
so how would you like me to invoke `lint-codespell` on CI? (without that would be IMHO very suboptimal and let typos sneak in)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3270
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Yaroslav Halchenko <debian@onerussian.com>
Co-committed-by: Yaroslav Halchenko <debian@onerussian.com>
2024-05-09 13:49:37 +00:00

67 lines
2.2 KiB
Go

// Copyright 2019 The Gitea Authors. All rights reserved.
// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
// SPDX-License-Identifier: MIT
package callout
import (
"strings"
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
)
// Transformer for GitHub's legacy callout markup.
type GitHubLegacyCalloutTransformer struct{}
func (g *GitHubLegacyCalloutTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) {
supportedCalloutTypes := map[string]bool{"Note": true, "Warning": true}
_ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
if !entering {
return ast.WalkContinue, nil
}
switch v := n.(type) {
case *ast.Blockquote:
// The first paragraph contains the callout type.
firstParagraph := v.FirstChild()
if firstParagraph.ChildCount() < 1 {
return ast.WalkContinue, nil
}
// In the legacy GitHub callout markup, the first node of the first
// paragraph should be an emphasis.
calloutNode, ok := firstParagraph.FirstChild().(*ast.Emphasis)
if !ok {
return ast.WalkContinue, nil
}
calloutText := string(calloutNode.Text(reader.Source()))
calloutType := strings.ToLower(calloutText)
// We only support "Note" and "Warning" callouts in legacy mode,
// match only those.
if _, has := supportedCalloutTypes[calloutText]; !has {
return ast.WalkContinue, nil
}
// Set the attention attribute on the emphasis
calloutNode.SetAttributeString("class", []byte("attention-"+calloutType))
// color the blockquote
v.SetAttributeString("class", []byte("attention-header attention-"+calloutType))
// Create new paragraph.
attentionParagraph := ast.NewParagraph()
attentionParagraph.SetAttributeString("class", []byte("attention-title"))
// Move the callout node to the paragraph and insert the paragraph.
attentionParagraph.AppendChild(attentionParagraph, NewAttention(calloutType))
attentionParagraph.AppendChild(attentionParagraph, calloutNode)
firstParagraph.Parent().InsertBefore(firstParagraph.Parent(), firstParagraph, attentionParagraph)
firstParagraph.RemoveChild(firstParagraph, calloutNode)
}
return ast.WalkContinue, nil
})
}