Add mathjax
This commit is contained in:
parent
4d9ef5917e
commit
085bd46440
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -0,0 +1,136 @@
|
||||||
|
package parsing
|
||||||
|
|
||||||
|
import (
|
||||||
|
gohtml "html"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/yuin/goldmark"
|
||||||
|
"github.com/yuin/goldmark/ast"
|
||||||
|
gast "github.com/yuin/goldmark/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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// Parser and delimiters
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
type mathjaxParser struct{}
|
||||||
|
|
||||||
|
var _ parser.BlockParser = mathjaxParser{}
|
||||||
|
|
||||||
|
func (s mathjaxParser) Trigger() []byte {
|
||||||
|
return []byte{'$'}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s mathjaxParser) Open(parent ast.Node, reader text.Reader, pc parser.Context) (ast.Node, parser.State) {
|
||||||
|
line, _ := reader.PeekLine()
|
||||||
|
lineStr := strings.TrimSpace(string(line))
|
||||||
|
|
||||||
|
if lineStr == "$$" {
|
||||||
|
return NewMathjax(), parser.NoChildren
|
||||||
|
} else {
|
||||||
|
return nil, parser.NoChildren
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s mathjaxParser) Continue(node ast.Node, reader text.Reader, pc parser.Context) parser.State {
|
||||||
|
line, _ := reader.PeekLine()
|
||||||
|
lineStr := strings.TrimSpace(string(line))
|
||||||
|
|
||||||
|
if lineStr == "$$" {
|
||||||
|
reader.Advance(len(line))
|
||||||
|
return parser.Close
|
||||||
|
}
|
||||||
|
|
||||||
|
node.(*MathjaxNode).Source += string(line)
|
||||||
|
return parser.Continue | parser.NoChildren
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s mathjaxParser) Close(node ast.Node, reader text.Reader, pc parser.Context) {}
|
||||||
|
|
||||||
|
func (s mathjaxParser) CanInterruptParagraph() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s mathjaxParser) CanAcceptIndentedLine() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// AST node
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
type MathjaxNode struct {
|
||||||
|
gast.BaseBlock
|
||||||
|
Source string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ gast.Node = &MathjaxNode{}
|
||||||
|
|
||||||
|
func (n *MathjaxNode) Dump(source []byte, level int) {
|
||||||
|
gast.DumpHelper(n, source, level, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
var KindMathjax = gast.NewNodeKind("Mathjax")
|
||||||
|
|
||||||
|
func (n *MathjaxNode) Kind() gast.NodeKind {
|
||||||
|
return KindMathjax
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMathjax() *MathjaxNode {
|
||||||
|
return &MathjaxNode{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// Renderer
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
type MathjaxHTMLRenderer struct {
|
||||||
|
html.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMathjaxHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
|
||||||
|
r := &MathjaxHTMLRenderer{
|
||||||
|
Config: html.NewConfig(),
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt.SetHTMLOption(&r.Config)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MathjaxHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
|
||||||
|
reg.Register(KindMathjax, r.renderMathjax)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MathjaxHTMLRenderer) renderMathjax(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
|
||||||
|
if entering {
|
||||||
|
w.WriteString("<div>\n")
|
||||||
|
w.WriteString("$$\n")
|
||||||
|
w.WriteString(gohtml.EscapeString(n.(*MathjaxNode).Source))
|
||||||
|
w.WriteString("$$\n")
|
||||||
|
w.WriteString("</div>\n")
|
||||||
|
}
|
||||||
|
return gast.WalkSkipChildren, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// Extension
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
type MathjaxExtension struct {
|
||||||
|
Preview bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e MathjaxExtension) Extend(m goldmark.Markdown) {
|
||||||
|
m.Parser().AddOptions(parser.WithBlockParsers(
|
||||||
|
util.Prioritized(mathjaxParser{}, 500),
|
||||||
|
))
|
||||||
|
m.Renderer().AddOptions(renderer.WithNodeRenderers(
|
||||||
|
util.Prioritized(NewMathjaxHTMLRenderer(), 500),
|
||||||
|
))
|
||||||
|
}
|
|
@ -97,6 +97,7 @@ var previewMarkdown = goldmark.New(
|
||||||
EmbedExtension{
|
EmbedExtension{
|
||||||
Preview: true,
|
Preview: true,
|
||||||
},
|
},
|
||||||
|
MathjaxExtension{},
|
||||||
bTag{},
|
bTag{},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -105,6 +106,7 @@ var realMarkdown = goldmark.New(
|
||||||
extension.GFM,
|
extension.GFM,
|
||||||
SpoilerExtension{},
|
SpoilerExtension{},
|
||||||
EmbedExtension{},
|
EmbedExtension{},
|
||||||
|
MathjaxExtension{},
|
||||||
bTag{},
|
bTag{},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
<input type="submit" class="button ml2" name="preview" value="{{ .PreviewLabel }}" />
|
<input type="submit" class="button ml2" name="preview" value="{{ .PreviewLabel }}" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="post post-preview mv3">
|
<div class="post post-preview mv3 mathjax">
|
||||||
<div id="preview" class="body contents"></div>
|
<div id="preview" class="body contents"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@
|
||||||
function updatePreview() {
|
function updatePreview() {
|
||||||
const previewHtml = parseMarkdown(tf.value);
|
const previewHtml = parseMarkdown(tf.value);
|
||||||
preview.innerHTML = previewHtml;
|
preview.innerHTML = previewHtml;
|
||||||
|
MathJax.typeset();
|
||||||
}
|
}
|
||||||
|
|
||||||
tf.addEventListener('input', () => {
|
tf.addEventListener('input', () => {
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
{{ end }}
|
{{ end }}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{{ block "extrahead" . }}{{ end }}
|
|
||||||
<link rel="stylesheet" href="{{ statictheme .Theme "theme.css" }}" />
|
<link rel="stylesheet" href="{{ statictheme .Theme "theme.css" }}" />
|
||||||
<link rel="stylesheet" href="{{ .ProjectCSSUrl }}" />
|
<link rel="stylesheet" href="{{ .ProjectCSSUrl }}" />
|
||||||
<link rel="apple-touch-icon" sizes="57x57" href="{{ static "apple-icon-57x57.png" }}">
|
<link rel="apple-touch-icon" sizes="57x57" href="{{ static "apple-icon-57x57.png" }}">
|
||||||
|
@ -58,6 +58,23 @@
|
||||||
<meta name="msapplication-TileColor" content="#ffffff">
|
<meta name="msapplication-TileColor" content="#ffffff">
|
||||||
<meta name="msapplication-TileImage" content="{{ static "ms-icon-144x144.png" }}">
|
<meta name="msapplication-TileImage" content="{{ static "ms-icon-144x144.png" }}">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
|
{{ if .MathjaxEnabled }}
|
||||||
|
<script>
|
||||||
|
MathJax = {
|
||||||
|
tex: {
|
||||||
|
inlineMath: [['$', '$']],
|
||||||
|
displayMath: [['$$', '$$']],
|
||||||
|
},
|
||||||
|
svg: {
|
||||||
|
fontCache: 'global',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script async src="{{ static "mathjax.js" }}"></script>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ block "extrahead" . }}{{ end }}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="{{ join " " .BodyClasses }}">
|
<body class="{{ join " " .BodyClasses }}">
|
||||||
|
|
|
@ -22,9 +22,10 @@ type BaseData struct {
|
||||||
User *User
|
User *User
|
||||||
Session *Session
|
Session *Session
|
||||||
|
|
||||||
IsProjectPage bool
|
IsProjectPage bool
|
||||||
Header Header
|
Header Header
|
||||||
Footer Footer
|
Footer Footer
|
||||||
|
MathjaxEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Header struct {
|
type Header struct {
|
||||||
|
|
|
@ -531,6 +531,7 @@ func ForumNewThread(c *RequestContext) ResponseData {
|
||||||
|
|
||||||
baseData := getBaseData(c)
|
baseData := getBaseData(c)
|
||||||
baseData.Title = "Create New Thread"
|
baseData.Title = "Create New Thread"
|
||||||
|
baseData.MathjaxEnabled = true
|
||||||
// TODO(ben): Set breadcrumbs
|
// TODO(ben): Set breadcrumbs
|
||||||
|
|
||||||
var res ResponseData
|
var res ResponseData
|
||||||
|
|
Loading…
Reference in New Issue