Live update Reveal config
This commit is contained in:
parent
82a651cd5d
commit
3f847e0b8b
5 changed files with 89 additions and 60 deletions
|
@ -51,8 +51,8 @@ var (
|
|||
hub := events.NewEventHub(
|
||||
wdfs,
|
||||
fnv.New32a(),
|
||||
events.FileNameTrigger(args[0]),
|
||||
events.FileNameTrigger(filepath.Base(cfg.ConfigFileInUse)),
|
||||
events.MutationReloadForFile(args[0]),
|
||||
events.MutationConfigReloadForFile(filepath.Base(cfg.ConfigFileInUse)),
|
||||
)
|
||||
|
||||
api.NoCache(app)
|
||||
|
|
|
@ -3,9 +3,10 @@ package config
|
|||
var (
|
||||
defaults = map[string]interface{}{
|
||||
"mermaid.theme": "forest",
|
||||
"reveal.theme": "beige",
|
||||
"theme": "beige",
|
||||
"codeTheme": "monokai",
|
||||
"transition": TransitionNone,
|
||||
"controlsLayout": ControlsLayoutEdges,
|
||||
"controls": true,
|
||||
"progress": true,
|
||||
"history": true,
|
||||
|
@ -23,11 +24,15 @@ const (
|
|||
TransitionConvex Transition = "convex"
|
||||
TransitionConcave Transition = "concave"
|
||||
TransitionZoom Transition = "zoom"
|
||||
|
||||
ControlsLayoutBottomRight ControlsLayout = "bottom-right"
|
||||
ControlsLayoutEdges ControlsLayout = "edges"
|
||||
)
|
||||
|
||||
type (
|
||||
Transition string
|
||||
Mermaid struct {
|
||||
Transition string
|
||||
ControlsLayout string
|
||||
Mermaid struct {
|
||||
Theme string `json:"theme"`
|
||||
}
|
||||
Rendering struct {
|
||||
|
@ -36,15 +41,16 @@ type (
|
|||
Stylesheets []string
|
||||
}
|
||||
Reveal struct {
|
||||
Theme string `json:"theme"`
|
||||
CodeTheme string `json:"codeTheme"`
|
||||
Transition Transition `json:"transition"`
|
||||
Controls bool `json:"controls"`
|
||||
Progress bool `json:"progress"`
|
||||
History bool `json:"history"`
|
||||
Center bool `json:"center"`
|
||||
SlideNumber bool `json:"slideNumber"`
|
||||
Menu struct {
|
||||
Theme string `json:"theme"`
|
||||
CodeTheme string `json:"codeTheme"`
|
||||
Transition Transition `json:"transition"`
|
||||
Controls bool `json:"controls"`
|
||||
ControlsLayout ControlsLayout `json:"controlsLayout"`
|
||||
Progress bool `json:"progress"`
|
||||
History bool `json:"history"`
|
||||
Center bool `json:"center"`
|
||||
SlideNumber bool `json:"slideNumber"`
|
||||
Menu struct {
|
||||
Numbers bool `json:"numbers"`
|
||||
UseTextContentForMissingTitles bool `json:"useTextContentForMissingTitles"`
|
||||
Transitions bool
|
||||
|
|
|
@ -21,14 +21,15 @@ const (
|
|||
)
|
||||
|
||||
type (
|
||||
ReloadTrigger interface {
|
||||
Triggers(ev fs.Event) bool
|
||||
EventMutation interface {
|
||||
OnEvent(in ContentEvent, ev fs.Event) (out ContentEvent)
|
||||
}
|
||||
ContentEvent struct {
|
||||
File string `json:"file"`
|
||||
FileNameHash string `json:"fileNameHash"`
|
||||
Timestamp string `json:"ts"`
|
||||
ForceReload bool `json:"forceReload"`
|
||||
ReloadConfig bool `json:"reloadConfig"`
|
||||
}
|
||||
EventSource interface {
|
||||
io.Closer
|
||||
|
@ -43,30 +44,35 @@ type (
|
|||
EventHandler
|
||||
OnError chan error
|
||||
}
|
||||
FileNameTrigger string
|
||||
FileSuffixTrigger string
|
||||
MutationReloadForFile string
|
||||
MutationConfigReloadForFile string
|
||||
)
|
||||
|
||||
func (t FileNameTrigger) Triggers(ev fs.Event) bool {
|
||||
fileBase := filepath.Base(ev.File)
|
||||
return strings.EqualFold(fileBase, string(t))
|
||||
func (t MutationReloadForFile) OnEvent(in ContentEvent, ev fs.Event) (out ContentEvent) {
|
||||
if strings.EqualFold(filepath.Base(ev.File), string(t)) {
|
||||
in.ForceReload = true
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
func (t FileSuffixTrigger) Triggers(ev fs.Event) bool {
|
||||
return strings.HasSuffix(strings.ToLower(filepath.Base(ev.File)), strings.ToLower(string(t)))
|
||||
func (t MutationConfigReloadForFile) OnEvent(in ContentEvent, ev fs.Event) (out ContentEvent) {
|
||||
if strings.EqualFold(filepath.Base(ev.File), string(t)) {
|
||||
in.ReloadConfig = true
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
func (f EventHandlerFunc) OnEvent(ev ContentEvent) error {
|
||||
return f(ev)
|
||||
}
|
||||
|
||||
func NewEventHub(eventSource EventSource, fileNameHash hash.Hash, triggers ...ReloadTrigger) *EventHub {
|
||||
func NewEventHub(eventSource EventSource, fileNameHash hash.Hash, mutations ...EventMutation) *EventHub {
|
||||
hub := &EventHub{
|
||||
FileNameHash: fileNameHash,
|
||||
reloadTriggers: triggers,
|
||||
source: eventSource,
|
||||
subscriptions: make(map[uuid.UUID]*subscription),
|
||||
done: make(chan struct{}),
|
||||
FileNameHash: fileNameHash,
|
||||
mutations: mutations,
|
||||
source: eventSource,
|
||||
subscriptions: make(map[uuid.UUID]*subscription),
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
go hub.processEvents()
|
||||
|
@ -75,12 +81,12 @@ func NewEventHub(eventSource EventSource, fileNameHash hash.Hash, triggers ...Re
|
|||
}
|
||||
|
||||
type EventHub struct {
|
||||
FileNameHash hash.Hash
|
||||
reloadTriggers []ReloadTrigger
|
||||
lock sync.RWMutex
|
||||
done chan struct{}
|
||||
source EventSource
|
||||
subscriptions map[uuid.UUID]*subscription
|
||||
FileNameHash hash.Hash
|
||||
mutations []EventMutation
|
||||
lock sync.RWMutex
|
||||
done chan struct{}
|
||||
source EventSource
|
||||
subscriptions map[uuid.UUID]*subscription
|
||||
}
|
||||
|
||||
func (h *EventHub) Subscribe(handler EventHandler) (id uuid.UUID, onError <-chan error) {
|
||||
|
@ -129,20 +135,16 @@ func (h *EventHub) notifySubscribers(ev fs.Event) {
|
|||
h.lock.RLock()
|
||||
defer h.lock.RUnlock()
|
||||
|
||||
var triggerReload bool
|
||||
for idx := range h.reloadTriggers {
|
||||
if triggerReload = h.reloadTriggers[idx].Triggers(ev); triggerReload {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ce := ContentEvent{
|
||||
File: fmt.Sprintf("/%s", ev.File),
|
||||
Timestamp: strconv.FormatInt(ev.Timestamp.Unix(), baseDecimal),
|
||||
ForceReload: triggerReload,
|
||||
FileNameHash: hex.EncodeToString(h.FileNameHash.Sum([]byte(path.Base(ev.File)))),
|
||||
}
|
||||
|
||||
for idx := range h.mutations {
|
||||
ce = h.mutations[idx].OnEvent(ce, ev)
|
||||
}
|
||||
|
||||
for _, handler := range h.subscriptions {
|
||||
if err := handler.OnEvent(ce); err != nil {
|
||||
handler.OnError <- err
|
||||
|
|
|
@ -3,6 +3,16 @@ codeTheme: monokai
|
|||
horizontalSeparator: ===
|
||||
verticalSeparator: ---
|
||||
transition: convex
|
||||
menu.numbers: false
|
||||
controlsLayout: edges
|
||||
controls: true
|
||||
progress: true
|
||||
history: true
|
||||
center: true
|
||||
slideNumber: true
|
||||
menu:
|
||||
numbers: false
|
||||
useTextContentForMissingTitles: true
|
||||
mermaid:
|
||||
theme: forest
|
||||
stylesheets:
|
||||
- custom.css
|
|
@ -25,9 +25,13 @@ async function setSlidesContent() {
|
|||
document.getElementById("content-root").innerHTML = contentDocument.documentElement.innerHTML
|
||||
}
|
||||
|
||||
async function initReveal() {
|
||||
async function getRevealConfig() {
|
||||
let resp = await fetch('/api/v1/config/reveal')
|
||||
let cfg = await resp.json()
|
||||
return await resp.json()
|
||||
}
|
||||
|
||||
async function initReveal() {
|
||||
let cfg = await getRevealConfig()
|
||||
Reveal.initialize({
|
||||
controls: cfg.controls,
|
||||
progress: cfg.progress,
|
||||
|
@ -97,20 +101,27 @@ function subscribeToEvents() {
|
|||
source.onmessage = (ev => {
|
||||
let obj = JSON.parse(ev.data);
|
||||
console.log(obj);
|
||||
if (obj.forceReload) {
|
||||
window.location.reload()
|
||||
} else {
|
||||
switch (true) {
|
||||
case obj.file.endsWith(".css"):
|
||||
let cssLink = document.querySelector(`link[rel=stylesheet][id="${obj.fileNameHash}"]`);
|
||||
cssLink.href = `${obj.file}?ts=${obj.ts}`
|
||||
break
|
||||
default:
|
||||
let elem = document.getElementById(obj.fileNameHash);
|
||||
if (elem !== null) {
|
||||
elem.src = `${obj.file}?ts=${obj.ts}`
|
||||
}
|
||||
}
|
||||
switch (true) {
|
||||
case obj.forceReload:
|
||||
window.location.reload()
|
||||
break
|
||||
case obj.reloadConfig:
|
||||
getRevealConfig().then(cfg => {
|
||||
Reveal.configure(cfg)
|
||||
})
|
||||
break
|
||||
default:
|
||||
switch (true) {
|
||||
case obj.file.endsWith(".css"):
|
||||
let cssLink = document.querySelector(`link[rel=stylesheet][id="${obj.fileNameHash}"]`);
|
||||
cssLink.href = `${obj.file}?ts=${obj.ts}`
|
||||
break
|
||||
default:
|
||||
let elem = document.getElementById(obj.fileNameHash);
|
||||
if (elem !== null) {
|
||||
elem.src = `${obj.file}?ts=${obj.ts}`
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Reference in a new issue