Skip to content

Commit

Permalink
Split slides first before rendering them
Browse files Browse the repository at this point in the history
- add some more config options
- cleanup code
- remove state machine
  • Loading branch information
prskr committed Dec 22, 2021
1 parent 33dadaf commit 7d3d3a5
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 220 deletions.
27 changes: 5 additions & 22 deletions api/views.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
package api

import (
"hash/fnv"
"io"

"github.com/gofiber/fiber/v2"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser"
"go.uber.org/multierr"

"github.com/baez90/goveal/config"
"github.com/baez90/goveal/fs"
"github.com/baez90/goveal/rendering"
)

const (
parserExtensions = parser.NoIntraEmphasis | parser.Tables | parser.FencedCode |
parser.Autolink | parser.Strikethrough | parser.SpaceHeadings | parser.HeadingIDs |
parser.BackslashLineBreak | parser.DefinitionLists | parser.MathJax | parser.Titleblock |
parser.OrderedListStart | parser.Attributes
)

type Views struct {
cfg *config.Components
wdfs fs.FS
Expand Down Expand Up @@ -54,20 +43,14 @@ func (p *Views) RenderedMarkdown(ctx *fiber.Ctx) (err error) {
return err
}

mdParser := parser.NewWithExtensions(parserExtensions)
rr := &rendering.RevealRenderer{
StateMachine: rendering.NewStateMachine("***", "---"),
Hash: fnv.New32a(),
var rendered []byte
if rendered, err = rendering.ToHTML(string(data), p.cfg.Rendering); err != nil {
return err
} else if _, err = ctx.Write(rendered); err != nil {
return err
}
renderer := html.NewRenderer(html.RendererOptions{
Flags: html.CommonFlags | html.HrefTargetBlank,
RenderNodeHook: rr.RenderHook,
})

ctx.Append(fiber.HeaderContentType, fiber.MIMETextHTML)
if _, err = ctx.Write(markdown.ToHTML(data, mdParser, renderer)); err != nil {
return err
}

return err
}
9 changes: 8 additions & 1 deletion config/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ var defaults = map[string]interface{}{
"slideNumber": true,
"menu.numbers": true,
"menu.useTextContentForMissingTitles": true,
"menu.transitions": true,
"menu.hideMissingTitles": true,
"menu.markers": true,
"menu.openButton": true,
}

const (
Expand Down Expand Up @@ -51,7 +55,10 @@ type (
Menu struct {
Numbers bool `json:"numbers"`
UseTextContentForMissingTitles bool `json:"useTextContentForMissingTitles"`
Transitions bool
Transitions bool `json:"transitions"`
HideMissingTitles bool `json:"hideMissingTitles"`
Markers bool `json:"markers"`
OpenButton bool `json:"openButton"`
} `json:"menu"`
}
Components struct {
Expand Down
8 changes: 6 additions & 2 deletions examples/goveal.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
theme: night
codeTheme: monokai
horizontalSeparator: ===
verticalSeparator: ---
horizontalSeparator: ---
verticalSeparator: '\*\*\*'
transition: convex
controlsLayout: edges
controls: true
Expand All @@ -12,6 +12,10 @@ slideNumber: true
menu:
numbers: false
useTextContentForMissingTitles: true
transitions: true
hideMissingTitles: false
markers: true
openButton: true
mermaid:
theme: forest
stylesheets:
Expand Down
3 changes: 2 additions & 1 deletion examples/slides.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ for (var j = 0; j < i; j++) {
### Mermaid

```mermaid
%%{init: {'theme': 'dark'}}%%
flowchart LR
a --> b & c--> d
```
Expand All @@ -102,7 +103,7 @@ flowchart LR
{line-numbers="1-2|3|4"}

```js
let a = 1;
let a = 1;
let b = 2;
let c = x => 1 + 2 + x;
c(3);
Expand Down
90 changes: 90 additions & 0 deletions rendering/html.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package rendering

import (
"bytes"
"fmt"
"html/template"
"regexp"

"github.com/gomarkdown/markdown/parser"

"github.com/baez90/goveal/config"
)

const (
parserExtensions = parser.NoIntraEmphasis | parser.Tables | parser.FencedCode |
parser.Autolink | parser.Strikethrough | parser.SpaceHeadings | parser.HeadingIDs |
parser.BackslashLineBreak | parser.DefinitionLists | parser.MathJax | parser.Titleblock |
parser.OrderedListStart | parser.Attributes
)

func ToHTML(markdown string, renderCfg config.Rendering) (rendered []byte, err error) {
var slides []rawSlide
if slides, err = splitIntoRawSlides(markdown, renderCfg); err != nil {
return nil, err
}

buf := templateRenderBufferPool.Get().(*bytes.Buffer)
defer func() {
buf.Reset()
templateRenderBufferPool.Put(buf)
}()

for idx := range slides {
if rendered, err := slides[idx].ToHTML(); err != nil {
return nil, err
} else {
buf.WriteString(string(rendered))
}
}

return buf.Bytes(), nil
}

type rawSlide struct {
Content string
Children []rawSlide
}

func (s rawSlide) HasNotes() bool {
return notesLineRegexp.MatchString(s.Content)
}

func (s rawSlide) ToHTML() (template.HTML, error) {
if rendered, err := renderTemplate("slide.gohtml", s); err != nil {
return "", err
} else {
//nolint:gosec // should not be sanitized
return template.HTML(rendered), nil
}
}

func splitIntoRawSlides(markdown string, renderCfg config.Rendering) ([]rawSlide, error) {
var (
verticalSplit, horizontalSplit *regexp.Regexp
err error
)
if verticalSplit, err = regexp.Compile(fmt.Sprintf(splitFormat, renderCfg.VerticalSeparator)); err != nil {
return nil, err
}

if horizontalSplit, err = regexp.Compile(fmt.Sprintf(splitFormat, renderCfg.HorizontalSeparator)); err != nil {
return nil, err
}

horizontalSlides := horizontalSplit.Split(markdown, -1)
slides := make([]rawSlide, 0, len(horizontalSlides))
for _, hs := range horizontalSlides {
s := rawSlide{
Content: hs,
}
verticalSlides := verticalSplit.Split(hs, -1)
s.Children = make([]rawSlide, 0, len(verticalSlides))
for _, vs := range verticalSlides {
s.Children = append(s.Children, rawSlide{Content: vs})
}
slides = append(slides, s)
}

return slides, nil
}
19 changes: 19 additions & 0 deletions rendering/patterns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package rendering

import (
"fmt"
"regexp"
)

const (
// language=regexp
notesRegex = `(?i)notes?:`
// language=regexp
splitFormat = `\r?\n%s\r?\n`
)

var (
htmlElementAttributesRegexp = regexp.MustCompile(`(?P<key>[a-z]+(-[a-z]+)*)="(?P<value>.+)"`)
notesRegexp = regexp.MustCompile(fmt.Sprintf(`^%s`, notesRegex))
notesLineRegexp = regexp.MustCompile(fmt.Sprintf(`\r?\n%s\r?\n`, notesRegex))
)
65 changes: 1 addition & 64 deletions rendering/render_to_reveal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,26 @@ package rendering

import (
"bytes"
"embed"
"encoding/hex"
"hash"
"html"
"html/template"
"io"
"path"
"regexp"
"sync"

"github.com/Masterminds/sprig/v3"
"github.com/gomarkdown/markdown/ast"
)

var (
//go:embed templates/*.gohtml
templatesFS embed.FS
templates *template.Template
templateRenderBufferPool = &sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
htmlElementAttributesRegexp = regexp.MustCompile(`(?P<key>[a-z]+(-[a-z]+)*)="(?P<value>.+)"`)
notesRegexp = regexp.MustCompile(`^(?i)notes?`)
)

const (
mermaidCodeBlock = "mermaid"
)

func init() {
var err error
templates = template.New("rendering").Funcs(sprig.FuncMap())
if templates, err = templates.ParseFS(templatesFS, "templates/*.gohtml"); err != nil {
panic(err)
}
}

type RevealRenderer struct {
StateMachine *StateMachine
Hash hash.Hash
hasNotes bool
Hash hash.Hash
}

//nolint:gocyclo // under construction
func (r *RevealRenderer) RenderHook(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
switch b := node.(type) {
case *ast.Document:
if entering {
_, _ = w.Write([]byte("<section>\n"))
if next := peekNextRuler(b); next != nil && string(next.Literal) == "***" {
_, _ = w.Write([]byte("<section>\n"))
r.StateMachine.CurrentState = StateTypeNested
}
} else {
_, _ = w.Write([]byte("</section>\n"))
}
return ast.GoToNext, false
case *ast.ListItem:
if entering {
return r.handleListItem(w, b)
Expand All @@ -72,7 +33,6 @@ func (r *RevealRenderer) RenderHook(w io.Writer, node ast.Node, entering bool) (
}
if notesRegexp.Match(b.Literal) {
_, err := w.Write([]byte(`<aside class="notes">`))
r.hasNotes = true
return ast.SkipChildren, err == nil
}
return ast.GoToNext, false
Expand All @@ -81,18 +41,6 @@ func (r *RevealRenderer) RenderHook(w io.Writer, node ast.Node, entering bool) (
return r.handleCodeBlock(w, b)
}
return ast.GoToNext, false
case *ast.HorizontalRule:
next := peekNextRuler(b)
input := string(b.Literal)
if next != nil {
input += string(next.Literal)
}
if r.hasNotes {
_, _ = w.Write([]byte(`</aside>`))
r.hasNotes = false
}
_, _ = w.Write(r.StateMachine.Accept(input))
return ast.GoToNext, true
case *ast.Image:
if entering {
return r.handleImage(w, b)
Expand Down Expand Up @@ -215,17 +163,6 @@ func renderCodeTemplate(templateName string, codeBlock *ast.CodeBlock) (output [
return renderTemplate(templateName, data)
}

func renderTemplate(templateName string, data interface{}) (output []byte, err error) {
buffer := templateRenderBufferPool.Get().(*bytes.Buffer)
defer func() {
buffer.Reset()
templateRenderBufferPool.Put(buffer)
}()

err = templates.ExecuteTemplate(buffer, templateName, data)
return buffer.Bytes(), err
}

func lineNumbers(attrs *ast.Attribute) string {
if attrs == nil || attrs.Attrs == nil {
return ""
Expand Down
Loading

0 comments on commit 7d3d3a5

Please sign in to comment.