mirror of
https://github.com/status-im/markdown.git
synced 2025-02-20 15:28:05 +00:00
rework the api a bit
This commit is contained in:
parent
16f2860a87
commit
892d084af3
@ -54,11 +54,7 @@ var (
|
||||
)
|
||||
|
||||
func runMarkdown(d []byte) string {
|
||||
htmlParams := markdown.HTMLRendererParameters{
|
||||
Flags: markdown.HTMLFlagsNone,
|
||||
}
|
||||
renderer := markdown.NewHTMLRenderer(htmlParams)
|
||||
html := markdown.Run(d, markdown.WithRenderer(renderer), markdown.WithExtensions(markdown.CommonExtensions))
|
||||
html := markdown.ToHTML(d, nil, nil)
|
||||
return string(html)
|
||||
}
|
||||
|
||||
|
@ -45,10 +45,11 @@ func execRecoverableTestSuite(t *testing.T, tests []string, params TestParams, s
|
||||
|
||||
func runMarkdown(input string, params TestParams) string {
|
||||
params.HTMLRendererParameters.Flags = params.HTMLFlags
|
||||
parser := NewParserWithExtensions(params.extensions)
|
||||
parser.ReferenceOverride = params.referenceOverride
|
||||
renderer := NewHTMLRenderer(params.HTMLRendererParameters)
|
||||
d := ParseAndRender([]byte(input), renderer,
|
||||
WithExtensions(params.extensions),
|
||||
WithRefOverride(params.referenceOverride))
|
||||
|
||||
d := ToHTML([]byte(input), parser, renderer)
|
||||
return string(d)
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,9 @@ const (
|
||||
SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering
|
||||
SmartypantsQuotesNBSP // Enable « French guillemets » (with Smartypants)
|
||||
TOC // Generate a table of contents
|
||||
|
||||
CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants |
|
||||
SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes
|
||||
)
|
||||
|
||||
var (
|
||||
|
237
markdown.go
237
markdown.go
@ -15,18 +15,14 @@ import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
//
|
||||
// Markdown parsing and processing
|
||||
//
|
||||
|
||||
// Version string of the package. Appears in the rendered document when
|
||||
// CompletePage flag is on.
|
||||
const Version = "2.0"
|
||||
|
||||
// Extensions is a bitfield of enabled extensions.
|
||||
// Extensions is a bitmask of enabled Parser extensions.
|
||||
type Extensions int
|
||||
|
||||
// Bitflags representing markdown parsing extensions.
|
||||
// Bit flags representing markdown parsing extensions.
|
||||
// Use | (or) to specify multiple extensions.
|
||||
const (
|
||||
NoExtensions Extensions = 0
|
||||
@ -47,9 +43,6 @@ const (
|
||||
BackslashLineBreak // Translate trailing backslashes into line breaks
|
||||
DefinitionLists // Render definition lists
|
||||
|
||||
CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants |
|
||||
SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes
|
||||
|
||||
CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode |
|
||||
Autolink | Strikethrough | SpaceHeadings | HeadingIDs |
|
||||
BackslashLineBreak | DefinitionLists
|
||||
@ -167,19 +160,42 @@ type Renderer interface {
|
||||
// for each character that triggers a response when parsing inline data.
|
||||
type inlineParser func(p *Parser, data []byte, offset int) (int, *Node)
|
||||
|
||||
// ReferenceOverrideFunc is expected to be called with a reference string and
|
||||
// return either a valid Reference type that the reference string maps to or
|
||||
// nil. If overridden is false, the default reference logic will be executed.
|
||||
// See the documentation in Options for more details on use-case.
|
||||
type ReferenceOverrideFunc func(reference string) (ref *Reference, overridden bool)
|
||||
|
||||
// Parser is a type that holds extensions and the runtime state used by
|
||||
// Parse, and the renderer. You can not use it directly, construct it with New.
|
||||
type Parser struct {
|
||||
|
||||
// ReferenceOverride is an optional function callback that is called every
|
||||
// time a reference is resolved. It can be set before starting parsing.
|
||||
//
|
||||
// In Markdown, the link reference syntax can be made to resolve a link to
|
||||
// a reference instead of an inline URL, in one of the following ways:
|
||||
//
|
||||
// * [link text][refid]
|
||||
// * [refid][]
|
||||
//
|
||||
// Usually, the refid is defined at the bottom of the Markdown document. If
|
||||
// this override function is provided, the refid is passed to the override
|
||||
// function first, before consulting the defined refids at the bottom. If
|
||||
// the override function indicates an override did not occur, the refids at
|
||||
// the bottom will be used to fill in the link details.
|
||||
ReferenceOverride ReferenceOverrideFunc
|
||||
|
||||
// after parsing, this is root of parsed ast
|
||||
Doc *Node
|
||||
|
||||
referenceOverride ReferenceOverrideFunc
|
||||
refs map[string]*reference
|
||||
inlineCallback [256]inlineParser
|
||||
extensions Extensions
|
||||
nesting int
|
||||
maxNesting int
|
||||
insideLink bool
|
||||
extensions Extensions
|
||||
|
||||
refs map[string]*reference
|
||||
inlineCallback [256]inlineParser
|
||||
nesting int
|
||||
maxNesting int
|
||||
insideLink bool
|
||||
|
||||
// Footnotes need to be ordered as well as available to quickly check for
|
||||
// presence. If a ref is also a footnote, it's stored both in refs and here
|
||||
@ -192,9 +208,58 @@ type Parser struct {
|
||||
allClosed bool
|
||||
}
|
||||
|
||||
// NewParser creates a markdown parser with CommonExtensions.
|
||||
func NewParser() *Parser {
|
||||
return NewParserWithExtensions(CommonExtensions)
|
||||
}
|
||||
|
||||
// NewParserWithExtensions creates a markdown parser with given extensions.
|
||||
// Before
|
||||
// for Run() to customize parser's behavior and the renderer.
|
||||
func NewParserWithExtensions(extension Extensions) *Parser {
|
||||
p := Parser{
|
||||
refs: make(map[string]*reference),
|
||||
maxNesting: 16,
|
||||
insideLink: false,
|
||||
Doc: NewNode(&DocumentData{}),
|
||||
extensions: extension,
|
||||
allClosed: true,
|
||||
}
|
||||
p.tip = p.Doc
|
||||
p.oldTip = p.Doc
|
||||
p.lastMatchedContainer = p.Doc
|
||||
|
||||
p.inlineCallback[' '] = maybeLineBreak
|
||||
p.inlineCallback['*'] = emphasis
|
||||
p.inlineCallback['_'] = emphasis
|
||||
if p.extensions&Strikethrough != 0 {
|
||||
p.inlineCallback['~'] = emphasis
|
||||
}
|
||||
p.inlineCallback['`'] = codeSpan
|
||||
p.inlineCallback['\n'] = lineBreak
|
||||
p.inlineCallback['['] = link
|
||||
p.inlineCallback['<'] = leftAngle
|
||||
p.inlineCallback['\\'] = escape
|
||||
p.inlineCallback['&'] = entity
|
||||
p.inlineCallback['!'] = maybeImage
|
||||
p.inlineCallback['^'] = maybeInlineFootnote
|
||||
if p.extensions&Autolink != 0 {
|
||||
p.inlineCallback['h'] = maybeAutoLink
|
||||
p.inlineCallback['m'] = maybeAutoLink
|
||||
p.inlineCallback['f'] = maybeAutoLink
|
||||
p.inlineCallback['H'] = maybeAutoLink
|
||||
p.inlineCallback['M'] = maybeAutoLink
|
||||
p.inlineCallback['F'] = maybeAutoLink
|
||||
}
|
||||
if p.extensions&Footnotes != 0 {
|
||||
p.notes = make([]*reference, 0)
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
||||
func (p *Parser) getRef(refid string) (ref *reference, found bool) {
|
||||
if p.referenceOverride != nil {
|
||||
r, overridden := p.referenceOverride(refid)
|
||||
if p.ReferenceOverride != nil {
|
||||
r, overridden := p.ReferenceOverride(refid)
|
||||
if overridden {
|
||||
if r == nil {
|
||||
return nil, false
|
||||
@ -254,131 +319,25 @@ type Reference struct {
|
||||
Text string
|
||||
}
|
||||
|
||||
// ReferenceOverrideFunc is expected to be called with a reference string and
|
||||
// return either a valid Reference type that the reference string maps to or
|
||||
// nil. If overridden is false, the default reference logic will be executed.
|
||||
// See the documentation in Options for more details on use-case.
|
||||
type ReferenceOverrideFunc func(reference string) (ref *Reference, overridden bool)
|
||||
|
||||
// NewParser creates a markdown parser. You can use the same With* functions as
|
||||
// for Run() to customize parser's behavior and the renderer.
|
||||
func NewParser(opts ...Option) *Parser {
|
||||
var p Parser
|
||||
for _, opt := range opts {
|
||||
opt(&p)
|
||||
}
|
||||
p.refs = make(map[string]*reference)
|
||||
p.maxNesting = 16
|
||||
p.insideLink = false
|
||||
docNode := NewNode(&DocumentData{})
|
||||
p.Doc = docNode
|
||||
p.tip = docNode
|
||||
p.oldTip = docNode
|
||||
p.lastMatchedContainer = docNode
|
||||
p.allClosed = true
|
||||
|
||||
p.inlineCallback[' '] = maybeLineBreak
|
||||
p.inlineCallback['*'] = emphasis
|
||||
p.inlineCallback['_'] = emphasis
|
||||
if p.extensions&Strikethrough != 0 {
|
||||
p.inlineCallback['~'] = emphasis
|
||||
}
|
||||
p.inlineCallback['`'] = codeSpan
|
||||
p.inlineCallback['\n'] = lineBreak
|
||||
p.inlineCallback['['] = link
|
||||
p.inlineCallback['<'] = leftAngle
|
||||
p.inlineCallback['\\'] = escape
|
||||
p.inlineCallback['&'] = entity
|
||||
p.inlineCallback['!'] = maybeImage
|
||||
p.inlineCallback['^'] = maybeInlineFootnote
|
||||
if p.extensions&Autolink != 0 {
|
||||
p.inlineCallback['h'] = maybeAutoLink
|
||||
p.inlineCallback['m'] = maybeAutoLink
|
||||
p.inlineCallback['f'] = maybeAutoLink
|
||||
p.inlineCallback['H'] = maybeAutoLink
|
||||
p.inlineCallback['M'] = maybeAutoLink
|
||||
p.inlineCallback['F'] = maybeAutoLink
|
||||
}
|
||||
if p.extensions&Footnotes != 0 {
|
||||
p.notes = make([]*reference, 0)
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
||||
// Option customizes the Markdown processor's default behavior.
|
||||
type Option func(*Parser)
|
||||
|
||||
// WithExtensions allows you to enable extensions
|
||||
func WithExtensions(e Extensions) Option {
|
||||
return func(p *Parser) {
|
||||
p.extensions = e
|
||||
}
|
||||
}
|
||||
|
||||
// WithNoExtensions turns off all extensions
|
||||
func WithNoExtensions() Option {
|
||||
return func(p *Parser) {
|
||||
p.extensions = NoExtensions
|
||||
}
|
||||
}
|
||||
|
||||
// WithRefOverride sets an optional function callback that is called every
|
||||
// time a reference is resolved.
|
||||
// ToHTML converts a markdown text in input and converts it to HTML.
|
||||
//
|
||||
// In Markdown, the link reference syntax can be made to resolve a link to
|
||||
// a reference instead of an inline URL, in one of the following ways:
|
||||
// You can optionally pass a parser and renderer, which allows to customize
|
||||
// a parser, a render or provide a renderer other than HTMLRenderer.
|
||||
//
|
||||
// * [link text][refid]
|
||||
// * [refid][]
|
||||
//
|
||||
// Usually, the refid is defined at the bottom of the Markdown document. If
|
||||
// this override function is provided, the refid is passed to the override
|
||||
// function first, before consulting the defined refids at the bottom. If
|
||||
// the override function indicates an override did not occur, the refids at
|
||||
// the bottom will be used to fill in the link details.
|
||||
func WithRefOverride(o ReferenceOverrideFunc) Option {
|
||||
return func(p *Parser) {
|
||||
p.referenceOverride = o
|
||||
// If you pass nil for both, we convert with CommonExtensions for
|
||||
// the parser and HTMLRenderer with CommonHTMLFlags.
|
||||
func ToHTML(input []byte, parser *Parser, renderer Renderer) []byte {
|
||||
if parser == nil {
|
||||
parser = NewParserWithExtensions(CommonExtensions)
|
||||
}
|
||||
if renderer == nil {
|
||||
params := HTMLRendererParameters{
|
||||
Flags: CommonHTMLFlags,
|
||||
}
|
||||
renderer = NewHTMLRenderer(params)
|
||||
}
|
||||
}
|
||||
|
||||
// ToHTML is the main entry point to Blackfriday. It parses and renders a
|
||||
// block of markdown-encoded text.
|
||||
//
|
||||
// The simplest invocation of Run takes one argument, input:
|
||||
// output := Run(input)
|
||||
// This will parse the input with CommonExtensions enabled and render it with
|
||||
// the default HTMLRenderer (with CommonHTMLFlags).
|
||||
//
|
||||
// Variadic arguments opts can customize the default behavior. Since Markdown
|
||||
// type does not contain exported fields, you can not use it directly. Instead,
|
||||
// use the With* functions. For example, this will call the most basic
|
||||
// functionality, with no extensions:
|
||||
// output := Run(input, WithNoExtensions())
|
||||
//
|
||||
// You can use any number of With* arguments, even contradicting ones. They
|
||||
// will be applied in order of appearance and the latter will override the
|
||||
// former:
|
||||
// output := Run(input, WithNoExtensions(), WithExtensions(exts),
|
||||
//
|
||||
func ToHTML(input []byte, opts ...Option) []byte {
|
||||
r := NewHTMLRenderer(HTMLRendererParameters{
|
||||
Flags: CommonHTMLFlags,
|
||||
})
|
||||
optList := []Option{WithExtensions(CommonExtensions)}
|
||||
optList = append(optList, opts...)
|
||||
parser := NewParser(optList...)
|
||||
parser.Parse(input)
|
||||
return parser.Render(r)
|
||||
}
|
||||
|
||||
// ParseAndRender parsers input and renders it with a renderer
|
||||
func ParseAndRender(input []byte, r Renderer, opts ...Option) []byte {
|
||||
optList := []Option{WithExtensions(CommonExtensions)}
|
||||
optList = append(optList, opts...)
|
||||
parser := NewParser(optList...)
|
||||
parser.Parse(input)
|
||||
return parser.Render(r)
|
||||
return parser.Render(renderer)
|
||||
}
|
||||
|
||||
// Render renders a parsed data in parser with a given renderer
|
||||
|
4
s/run-bench.sh
Executable file
4
s/run-bench.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
set -u -e -o pipefail -o verbose
|
||||
|
||||
go test -bench=. -test.benchmem
|
Loading…
x
Reference in New Issue
Block a user