Initial commit
This commit is contained in:
commit
a4681f9565
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Pierre-Olivier Mercier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
22
README.md
Normal file
22
README.md
Normal file
@ -0,0 +1,22 @@
|
||||
# goldmark-superscript
|
||||
|
||||
[GoldMark](https://github.com/yuin/goldmark/) superscript extension.
|
||||
|
||||
This implements the [`superscript`](https://pandoc.org/MANUAL.html#extension-bracketed_spans) of pandoc.
|
||||
|
||||
```markdown
|
||||
H~2~O is a liquid. 2^10^ is 1024.
|
||||
```
|
||||
|
||||
```html
|
||||
<p>H~2~O is a liquid. 2<sup>10</sup> is 1024.</p>
|
||||
```
|
||||
|
||||
```go
|
||||
var md = goldmark.New(superscript.Enable)
|
||||
var source = []byte("H~2~O is a liquid. 2^10^ is 1024.")
|
||||
err := md.Convert(source, os.Stdout)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
22
ast.go
Normal file
22
ast.go
Normal file
@ -0,0 +1,22 @@
|
||||
package superscript
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/yuin/goldmark/ast"
|
||||
)
|
||||
|
||||
// Kind is the kind of hashtag AST nodes.
|
||||
var Kind = ast.NewNodeKind("Superscript")
|
||||
|
||||
// Node is a parsed Superscript node.
|
||||
type Node struct {
|
||||
ast.BaseInline
|
||||
}
|
||||
|
||||
func (*Node) Kind() ast.NodeKind { return Kind }
|
||||
|
||||
func (n *Node) Dump(src []byte, level int) {
|
||||
fmt.Printf("%ssuperscript: \"%s\"\n", strings.Repeat(" ", level), n.Text(src))
|
||||
}
|
34
extend.go
Normal file
34
extend.go
Normal file
@ -0,0 +1,34 @@
|
||||
package superscript
|
||||
|
||||
import (
|
||||
"github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
"github.com/yuin/goldmark/renderer"
|
||||
"github.com/yuin/goldmark/util"
|
||||
)
|
||||
|
||||
type Extender struct{}
|
||||
|
||||
var (
|
||||
defaultParser = new(superscriptParser)
|
||||
defaultRenderer = new(superscriptRenderer)
|
||||
)
|
||||
|
||||
func (e *Extender) Extend(m goldmark.Markdown) {
|
||||
m.Parser().AddOptions(
|
||||
parser.WithInlineParsers(
|
||||
util.Prioritized(defaultParser, 100),
|
||||
),
|
||||
)
|
||||
m.Renderer().AddOptions(
|
||||
renderer.WithNodeRenderers(
|
||||
util.Prioritized(defaultRenderer, 100),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// Extension is a goldmark.Extender with markdown inline attributes support.
|
||||
var Extension goldmark.Extender = new(Extender)
|
||||
|
||||
// Enable is a goldmark.Option with inline attributes support.
|
||||
var Enable = goldmark.WithExtensions(Extension)
|
22
extend_test.go
Normal file
22
extend_test.go
Normal file
@ -0,0 +1,22 @@
|
||||
package superscript
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/yuin/goldmark"
|
||||
)
|
||||
|
||||
func TestAttributes(t *testing.T) {
|
||||
source := []byte(`
|
||||
H~2~O is a liquid. 2^10^ is 1024.
|
||||
`)
|
||||
|
||||
var md = goldmark.New(Enable)
|
||||
err := md.Convert(source, os.Stdout)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
||||
module github.com/nemunaire/goldmark-superscript
|
||||
|
||||
go 1.18
|
||||
|
||||
require github.com/yuin/goldmark v1.5.6
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
||||
github.com/yuin/goldmark v1.5.6 h1:COmQAWTCcGetChm3Ig7G/t8AFAN00t+o8Mt4cf7JpwA=
|
||||
github.com/yuin/goldmark v1.5.6/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
46
parser.go
Normal file
46
parser.go
Normal file
@ -0,0 +1,46 @@
|
||||
package superscript
|
||||
|
||||
import (
|
||||
"github.com/yuin/goldmark/ast"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
"github.com/yuin/goldmark/text"
|
||||
)
|
||||
|
||||
type superscriptDelimiterProcessor struct {
|
||||
}
|
||||
|
||||
func (p *superscriptDelimiterProcessor) IsDelimiter(b byte) bool {
|
||||
return b == '^'
|
||||
}
|
||||
|
||||
func (p *superscriptDelimiterProcessor) CanOpenCloser(opener, closer *parser.Delimiter) bool {
|
||||
return opener.Char == closer.Char
|
||||
}
|
||||
|
||||
func (p *superscriptDelimiterProcessor) OnMatch(consumes int) ast.Node {
|
||||
return &Node{}
|
||||
}
|
||||
|
||||
var defaultEmphasisDelimiterProcessor = &superscriptDelimiterProcessor{}
|
||||
|
||||
type superscriptParser struct {
|
||||
}
|
||||
|
||||
var defaultSuperscriptParser = &superscriptParser{}
|
||||
|
||||
func (s *superscriptParser) Trigger() []byte {
|
||||
return []byte{'^'}
|
||||
}
|
||||
|
||||
func (s *superscriptParser) Parse(parent ast.Node, block text.Reader, pc parser.Context) ast.Node {
|
||||
before := block.PrecendingCharacter()
|
||||
line, segment := block.PeekLine()
|
||||
node := parser.ScanDelimiter(line, before, 1, defaultEmphasisDelimiterProcessor)
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
node.Segment = segment.WithStop(segment.Start + node.OriginalLength)
|
||||
block.Advance(node.OriginalLength)
|
||||
pc.PushDelimiter(node)
|
||||
return node
|
||||
}
|
44
render.go
Normal file
44
render.go
Normal file
@ -0,0 +1,44 @@
|
||||
package superscript
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yuin/goldmark/ast"
|
||||
"github.com/yuin/goldmark/renderer"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
"github.com/yuin/goldmark/util"
|
||||
)
|
||||
|
||||
type superscriptRenderer struct{}
|
||||
|
||||
func (r *superscriptRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
|
||||
reg.Register(Kind, r.Render)
|
||||
}
|
||||
|
||||
func (r *superscriptRenderer) Render(w util.BufWriter, _ []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||
n, ok := node.(*Node)
|
||||
if !ok {
|
||||
return ast.WalkStop, fmt.Errorf("unexpected node %T, expected *Node", node)
|
||||
}
|
||||
|
||||
if entering {
|
||||
if err := r.enter(w, n); err != nil {
|
||||
return ast.WalkStop, err
|
||||
}
|
||||
} else {
|
||||
r.exit(w, n)
|
||||
}
|
||||
|
||||
return ast.WalkContinue, nil
|
||||
}
|
||||
|
||||
func (r *superscriptRenderer) enter(w util.BufWriter, n *Node) error {
|
||||
w.WriteString(`<sup`)
|
||||
html.RenderAttributes(w, n, nil)
|
||||
w.WriteString(`>`)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *superscriptRenderer) exit(w util.BufWriter, n *Node) {
|
||||
w.WriteString("</sup>")
|
||||
}
|
Loading…
Reference in New Issue
Block a user