mirror of
https://github.com/go-gitea/gitea
synced 2024-09-19 18:26:04 +00:00
792b4dba2c
* update github.com/blevesearch/bleve v2.0.2 -> v2.0.3 * github.com/denisenkom/go-mssqldb v0.9.0 -> v0.10.0 * github.com/editorconfig/editorconfig-core-go v2.4.1 -> v2.4.2 * github.com/go-chi/cors v1.1.1 -> v1.2.0 * github.com/go-git/go-billy v5.0.0 -> v5.1.0 * github.com/go-git/go-git v5.2.0 -> v5.3.0 * github.com/go-ldap/ldap v3.2.4 -> v3.3.0 * github.com/go-redis/redis v8.6.0 -> v8.8.2 * github.com/go-sql-driver/mysql v1.5.0 -> v1.6.0 * github.com/go-swagger/go-swagger v0.26.1 -> v0.27.0 * github.com/lib/pq v1.9.0 -> v1.10.1 * github.com/mattn/go-sqlite3 v1.14.6 -> v1.14.7 * github.com/go-testfixtures/testfixtures v3.5.0 -> v3.6.0 * github.com/issue9/identicon v1.0.1 -> v1.2.0 * github.com/klauspost/compress v1.11.8 -> v1.12.1 * github.com/mgechev/revive v1.0.3 -> v1.0.6 * github.com/microcosm-cc/bluemonday v1.0.7 -> v1.0.8 * github.com/niklasfasching/go-org v1.4.0 -> v1.5.0 * github.com/olivere/elastic v7.0.22 -> v7.0.24 * github.com/pelletier/go-toml v1.8.1 -> v1.9.0 * github.com/prometheus/client_golang v1.9.0 -> v1.10.0 * github.com/xanzy/go-gitlab v0.44.0 -> v0.48.0 * github.com/yuin/goldmark v1.3.3 -> v1.3.5 * github.com/6543/go-version v1.2.4 -> v1.3.1 * do github.com/lib/pq v1.10.0 -> v1.10.1 again ...
271 lines
8.0 KiB
Go
Vendored
271 lines
8.0 KiB
Go
Vendored
package extension
|
|
|
|
import (
|
|
"github.com/yuin/goldmark"
|
|
gast "github.com/yuin/goldmark/ast"
|
|
"github.com/yuin/goldmark/extension/ast"
|
|
"github.com/yuin/goldmark/parser"
|
|
"github.com/yuin/goldmark/renderer"
|
|
"github.com/yuin/goldmark/renderer/html"
|
|
"github.com/yuin/goldmark/text"
|
|
"github.com/yuin/goldmark/util"
|
|
)
|
|
|
|
type definitionListParser struct {
|
|
}
|
|
|
|
var defaultDefinitionListParser = &definitionListParser{}
|
|
|
|
// NewDefinitionListParser return a new parser.BlockParser that
|
|
// can parse PHP Markdown Extra Definition lists.
|
|
func NewDefinitionListParser() parser.BlockParser {
|
|
return defaultDefinitionListParser
|
|
}
|
|
|
|
func (b *definitionListParser) Trigger() []byte {
|
|
return []byte{':'}
|
|
}
|
|
|
|
func (b *definitionListParser) Open(parent gast.Node, reader text.Reader, pc parser.Context) (gast.Node, parser.State) {
|
|
if _, ok := parent.(*ast.DefinitionList); ok {
|
|
return nil, parser.NoChildren
|
|
}
|
|
line, _ := reader.PeekLine()
|
|
pos := pc.BlockOffset()
|
|
indent := pc.BlockIndent()
|
|
if pos < 0 || line[pos] != ':' || indent != 0 {
|
|
return nil, parser.NoChildren
|
|
}
|
|
|
|
last := parent.LastChild()
|
|
// need 1 or more spaces after ':'
|
|
w, _ := util.IndentWidth(line[pos+1:], pos+1)
|
|
if w < 1 {
|
|
return nil, parser.NoChildren
|
|
}
|
|
if w >= 8 { // starts with indented code
|
|
w = 5
|
|
}
|
|
w += pos + 1 /* 1 = ':' */
|
|
|
|
para, lastIsParagraph := last.(*gast.Paragraph)
|
|
var list *ast.DefinitionList
|
|
status := parser.HasChildren
|
|
var ok bool
|
|
if lastIsParagraph {
|
|
list, ok = last.PreviousSibling().(*ast.DefinitionList)
|
|
if ok { // is not first item
|
|
list.Offset = w
|
|
list.TemporaryParagraph = para
|
|
} else { // is first item
|
|
list = ast.NewDefinitionList(w, para)
|
|
status |= parser.RequireParagraph
|
|
}
|
|
} else if list, ok = last.(*ast.DefinitionList); ok { // multiple description
|
|
list.Offset = w
|
|
list.TemporaryParagraph = nil
|
|
} else {
|
|
return nil, parser.NoChildren
|
|
}
|
|
|
|
return list, status
|
|
}
|
|
|
|
func (b *definitionListParser) Continue(node gast.Node, reader text.Reader, pc parser.Context) parser.State {
|
|
line, _ := reader.PeekLine()
|
|
if util.IsBlank(line) {
|
|
return parser.Continue | parser.HasChildren
|
|
}
|
|
list, _ := node.(*ast.DefinitionList)
|
|
w, _ := util.IndentWidth(line, reader.LineOffset())
|
|
if w < list.Offset {
|
|
return parser.Close
|
|
}
|
|
pos, padding := util.IndentPosition(line, reader.LineOffset(), list.Offset)
|
|
reader.AdvanceAndSetPadding(pos, padding)
|
|
return parser.Continue | parser.HasChildren
|
|
}
|
|
|
|
func (b *definitionListParser) Close(node gast.Node, reader text.Reader, pc parser.Context) {
|
|
// nothing to do
|
|
}
|
|
|
|
func (b *definitionListParser) CanInterruptParagraph() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *definitionListParser) CanAcceptIndentedLine() bool {
|
|
return false
|
|
}
|
|
|
|
type definitionDescriptionParser struct {
|
|
}
|
|
|
|
var defaultDefinitionDescriptionParser = &definitionDescriptionParser{}
|
|
|
|
// NewDefinitionDescriptionParser return a new parser.BlockParser that
|
|
// can parse definition description starts with ':'.
|
|
func NewDefinitionDescriptionParser() parser.BlockParser {
|
|
return defaultDefinitionDescriptionParser
|
|
}
|
|
|
|
func (b *definitionDescriptionParser) Trigger() []byte {
|
|
return []byte{':'}
|
|
}
|
|
|
|
func (b *definitionDescriptionParser) Open(parent gast.Node, reader text.Reader, pc parser.Context) (gast.Node, parser.State) {
|
|
line, _ := reader.PeekLine()
|
|
pos := pc.BlockOffset()
|
|
indent := pc.BlockIndent()
|
|
if pos < 0 || line[pos] != ':' || indent != 0 {
|
|
return nil, parser.NoChildren
|
|
}
|
|
list, _ := parent.(*ast.DefinitionList)
|
|
if list == nil {
|
|
return nil, parser.NoChildren
|
|
}
|
|
para := list.TemporaryParagraph
|
|
list.TemporaryParagraph = nil
|
|
if para != nil {
|
|
lines := para.Lines()
|
|
l := lines.Len()
|
|
for i := 0; i < l; i++ {
|
|
term := ast.NewDefinitionTerm()
|
|
segment := lines.At(i)
|
|
term.Lines().Append(segment.TrimRightSpace(reader.Source()))
|
|
list.AppendChild(list, term)
|
|
}
|
|
para.Parent().RemoveChild(para.Parent(), para)
|
|
}
|
|
cpos, padding := util.IndentPosition(line[pos+1:], pos+1, list.Offset-pos-1)
|
|
reader.AdvanceAndSetPadding(cpos+1, padding)
|
|
|
|
return ast.NewDefinitionDescription(), parser.HasChildren
|
|
}
|
|
|
|
func (b *definitionDescriptionParser) Continue(node gast.Node, reader text.Reader, pc parser.Context) parser.State {
|
|
// definitionListParser detects end of the description.
|
|
// so this method will never be called.
|
|
return parser.Continue | parser.HasChildren
|
|
}
|
|
|
|
func (b *definitionDescriptionParser) Close(node gast.Node, reader text.Reader, pc parser.Context) {
|
|
desc := node.(*ast.DefinitionDescription)
|
|
desc.IsTight = !desc.HasBlankPreviousLines()
|
|
if desc.IsTight {
|
|
for gc := desc.FirstChild(); gc != nil; gc = gc.NextSibling() {
|
|
paragraph, ok := gc.(*gast.Paragraph)
|
|
if ok {
|
|
textBlock := gast.NewTextBlock()
|
|
textBlock.SetLines(paragraph.Lines())
|
|
desc.ReplaceChild(desc, paragraph, textBlock)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (b *definitionDescriptionParser) CanInterruptParagraph() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *definitionDescriptionParser) CanAcceptIndentedLine() bool {
|
|
return false
|
|
}
|
|
|
|
// DefinitionListHTMLRenderer is a renderer.NodeRenderer implementation that
|
|
// renders DefinitionList nodes.
|
|
type DefinitionListHTMLRenderer struct {
|
|
html.Config
|
|
}
|
|
|
|
// NewDefinitionListHTMLRenderer returns a new DefinitionListHTMLRenderer.
|
|
func NewDefinitionListHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
|
|
r := &DefinitionListHTMLRenderer{
|
|
Config: html.NewConfig(),
|
|
}
|
|
for _, opt := range opts {
|
|
opt.SetHTMLOption(&r.Config)
|
|
}
|
|
return r
|
|
}
|
|
|
|
// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
|
|
func (r *DefinitionListHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
|
|
reg.Register(ast.KindDefinitionList, r.renderDefinitionList)
|
|
reg.Register(ast.KindDefinitionTerm, r.renderDefinitionTerm)
|
|
reg.Register(ast.KindDefinitionDescription, r.renderDefinitionDescription)
|
|
}
|
|
|
|
// DefinitionListAttributeFilter defines attribute names which dl elements can have.
|
|
var DefinitionListAttributeFilter = html.GlobalAttributeFilter
|
|
|
|
func (r *DefinitionListHTMLRenderer) renderDefinitionList(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
|
|
if entering {
|
|
if n.Attributes() != nil {
|
|
_, _ = w.WriteString("<dl")
|
|
html.RenderAttributes(w, n, DefinitionListAttributeFilter)
|
|
_, _ = w.WriteString(">\n")
|
|
} else {
|
|
_, _ = w.WriteString("<dl>\n")
|
|
}
|
|
} else {
|
|
_, _ = w.WriteString("</dl>\n")
|
|
}
|
|
return gast.WalkContinue, nil
|
|
}
|
|
|
|
// DefinitionTermAttributeFilter defines attribute names which dd elements can have.
|
|
var DefinitionTermAttributeFilter = html.GlobalAttributeFilter
|
|
|
|
func (r *DefinitionListHTMLRenderer) renderDefinitionTerm(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
|
|
if entering {
|
|
if n.Attributes() != nil {
|
|
_, _ = w.WriteString("<dt")
|
|
html.RenderAttributes(w, n, DefinitionTermAttributeFilter)
|
|
_ = w.WriteByte('>')
|
|
} else {
|
|
_, _ = w.WriteString("<dt>")
|
|
}
|
|
} else {
|
|
_, _ = w.WriteString("</dt>\n")
|
|
}
|
|
return gast.WalkContinue, nil
|
|
}
|
|
|
|
// DefinitionDescriptionAttributeFilter defines attribute names which dd elements can have.
|
|
var DefinitionDescriptionAttributeFilter = html.GlobalAttributeFilter
|
|
|
|
func (r *DefinitionListHTMLRenderer) renderDefinitionDescription(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
|
|
if entering {
|
|
n := node.(*ast.DefinitionDescription)
|
|
_, _ = w.WriteString("<dd")
|
|
if n.Attributes() != nil {
|
|
html.RenderAttributes(w, n, DefinitionDescriptionAttributeFilter)
|
|
}
|
|
if n.IsTight {
|
|
_, _ = w.WriteString(">")
|
|
} else {
|
|
_, _ = w.WriteString(">\n")
|
|
}
|
|
} else {
|
|
_, _ = w.WriteString("</dd>\n")
|
|
}
|
|
return gast.WalkContinue, nil
|
|
}
|
|
|
|
type definitionList struct {
|
|
}
|
|
|
|
// DefinitionList is an extension that allow you to use PHP Markdown Extra Definition lists.
|
|
var DefinitionList = &definitionList{}
|
|
|
|
func (e *definitionList) Extend(m goldmark.Markdown) {
|
|
m.Parser().AddOptions(parser.WithBlockParsers(
|
|
util.Prioritized(NewDefinitionListParser(), 101),
|
|
util.Prioritized(NewDefinitionDescriptionParser(), 102),
|
|
))
|
|
m.Renderer().AddOptions(renderer.WithNodeRenderers(
|
|
util.Prioritized(NewDefinitionListHTMLRenderer(), 500),
|
|
))
|
|
}
|