Documentation
¶
Overview ¶
Package whynot shows Markdown documents in Go programs, such as games and GUI apps: it lays a document out, draws it, and lets the user scroll through it and click its links. It draws through a small interface rather than a particular graphics library, and receives input as plain values, so it works with any framework a backend adapts: whynot comes with backends for Ebitengine and Gio.
Overview ¶
The package has four main types:
- Parse turns Markdown into a Document.
- A View lays a Document out and draws it into a rectangle of a canvas, scrolled to a position. It only lays out what's on screen, so long documents cost no more than short ones.
- A Controller turns the user's input into what it does to a View: scrolling (by wheel, touch, scrollbar or command), highlighting the link under the pointer, and reporting clicks.
- A Panel is a View and a Controller together, with settings that survive showing another document: the simplest way to put a document on screen.
A View is given what decides how the document looks:
- a StyleSheet, for colors, text styles, margins and scrollbars, made by a package under styles/, such as styles/simpletheme;
- a fonts.FaceSelector, for the fonts the text is drawn with (see package fonts);
- optionally, an images.Source, for where images come from (WithImageSource; see package images).
Parse can be given code-block plugins (WithCodeBlockPlugin; see package codeblocks), for syntax highlighting or diagrams.
Showing a document ¶
A backend provides two things: an input.Source that reads the user's input from the framework, and a canvas.Canvas to draw on. Here is how to use them with Ebitengine.
Once, when your program starts, make the backend's input reader and renderer, and set a Panel up:
var source ebitenbackend.Input // reads Ebitengine's input: an input.Source renderer := ebitenbackend.New() // keeps image textures and glyph caches across frames doc := whynot.Parse(markdown) view := whynot.NewView(doc, fonts.NewGoSelector(), simpletheme.DarkStyleSheet) panel := whynot.NewPanel(view, bounds) // where it's drawn on the screen panel.SetScale(scale) // the screen's density
Then, every frame, pass the input to the Panel, with the time, and react to what happened. With Ebitengine, do that in your game's Update method:
events := panel.Frame(source.Events(), now) // react to events, such as a LinkClick
Draw the Panel every frame too. Ebitengine gives your game's Draw method the screen image to draw on each time, so make a canvas onto it each time as well. That's cheap: the renderer holds what's worth keeping.
panel.Draw(renderer.NewCanvas(screen), now)
With Gio, a giobackend.Input and a giobackend.Renderer play the same roles, and the frame loop is shaped by Gio's events instead. The packages backends/ebitenbackend and backends/giobackend each show a complete program. When the window is resized, the screen changes or the user zooms, call Panel.SetBounds, Panel.SetScale or Panel.SetZoom: the document is laid out again, keeping the scroll position.
A Panel, or a View and a Controller ¶
A Panel covers what most programs need. Use a View and a Controller directly for more control: you can then drive a View with input of your own, fit it into a structure of your own, or move it by code alone (View.ScrollBy, View.ScrollToAnchor, View.ScrollToRatio). A View also answers questions about what it shows: the link under the pointer (View.HoveredLink), the part of the document in view (View.VisibleRange), the heading currently on screen (View.CurrentHeadingID).
Coordinates ¶
whynot uses one coordinate space: the canvas's. The Canvas a View draws on, the input events a Controller acts on, a View's or Panel's bounds, and everything a View reports by position (View.HitTest, View.LinkAt) share the same origin and the same unit, canvas pixels: device pixels for whynot's own backends. Where the canvas sits in a window is the backend's business, not whynot's.
A View is a window onto that space: View.SetBounds says where it is, and it draws and answers only there. There is no separate coordinate space of the View's own to convert to and from: a point a Controller receives can be passed to HitTest as it is, and the rectangle HitTest returns can be drawn on the canvas as it is.
Distances are in canvas pixels too, such as View.ScrollBy's. The scale relates them to logical pixels, the unit of a StyleSheet's dimensions: it's the number of canvas pixels per logical pixel (View.SetScale), and a View is laid out at its scale times its zoom (View.SetZoom). Command scrolling (Controller.ScrollDown, Controller.ScrollLeft and the like, also on a Panel) steps in logical pixels without the zoom, so a step covers the same distance on screen at any zoom.
How far a View is scrolled into its document isn't in pixels, because the document's height is an estimate until all of it has been laid out: View.VisibleRange reports the part in view as fractions of the height, and View.ScrollToRatio scrolls to one.
Events and state ¶
What happens in a View that a program may react to comes out of Controller.Frame as Event values, in order: the counterpart of the input events going in. They're a sealed set, like input's, so new kinds can be added without breaking anyone:
for _, e := range panel.Frame(source.Events(), now) {
switch e := e.(type) {
case whynot.LinkClick:
// follow e.Destination: load another document, say
case whynot.AnchorClick:
// already scrolled to e.ID, unless turned off
}
}
A Controller only reports events. A Panel also acts on one: it scrolls to an AnchorClick's heading, the way a browser follows a "#id" link, unless Panel.SetAnchorScrolling turns that off for a program that handles it itself, to record history first, say. Following a LinkClick is always up to the program.
What's true at the moment, rather than what happened, is read from the View when needed, such as the link under the pointer (View.HoveredLink), which a program may show in a status bar.
Related packages ¶
The contracts whynot works with each have a package of their own, so that each can be implemented separately:
- canvas and input: what a backend provides, drawing and input events. The backends are under backends/.
- fonts, images and codeblocks: fonts, image loading and code-block plugins. Ready-made implementations are in their subpackages: fonts/systemfont (fonts installed on the system), codeblocks/chromahighlight (syntax highlighting) and codeblocks/kroki (diagrams).
- Stylesheets: styles/simpletheme, with light and dark themes.
Index ¶
- type AnchorClick
- type Controller
- func (c *Controller) Animating() bool
- func (c *Controller) Frame(events []input.Event, now time.Duration) []Event
- func (c *Controller) PageDown()
- func (c *Controller) PageUp()
- func (c *Controller) Scale() float64
- func (c *Controller) ScrollDown()
- func (c *Controller) ScrollLeft() bool
- func (c *Controller) ScrollRight() bool
- func (c *Controller) ScrollUp()
- func (c *Controller) SetScale(s float64)
- func (c *Controller) SetView(v *View)
- func (c *Controller) View() *View
- type Document
- type Event
- type LinkClick
- type Panel
- func (p *Panel) Animating() bool
- func (p *Panel) Bounds() image.Rectangle
- func (p *Panel) Draw(dst canvas.Canvas, now time.Duration)
- func (p *Panel) Frame(events []input.Event, now time.Duration) []Event
- func (p *Panel) PageDown()
- func (p *Panel) PageUp()
- func (p *Panel) Scale() float64
- func (p *Panel) ScrollDown()
- func (p *Panel) ScrollLeft() bool
- func (p *Panel) ScrollRight() bool
- func (p *Panel) ScrollUp()
- func (p *Panel) SetAnchorScrolling(on bool)
- func (p *Panel) SetBounds(r image.Rectangle)
- func (p *Panel) SetScale(s float64)
- func (p *Panel) SetScrollbar(on bool)
- func (p *Panel) SetStyleSheet(s StyleSheet)
- func (p *Panel) SetView(v *View)
- func (p *Panel) SetZoom(zoom float64)
- func (p *Panel) View() *View
- func (p *Panel) Zoom() float64
- type ParseOption
- type ScrollPosition
- type StyleSheet
- type TOCEntry
- type View
- func (v *View) Bounds() image.Rectangle
- func (v *View) CurrentHeadingID() (id string, ok bool)
- func (v *View) Document() *Document
- func (v *View) Draw(dst canvas.Canvas, now time.Duration)
- func (v *View) HighlightColor() color.Color
- func (v *View) HitTest(x, y int) (r image.Rectangle, ok bool)
- func (v *View) HoveredLink() (destination string, ok bool)
- func (v *View) LinkAt(x, y int) (destination string, ok bool)
- func (v *View) RestoreScrollPosition(p ScrollPosition)
- func (v *View) Scale() float64
- func (v *View) ScrollBy(dy float64)
- func (v *View) ScrollPosition() ScrollPosition
- func (v *View) ScrollToAnchor(id string) bool
- func (v *View) ScrollToRatio(ratio float64)
- func (v *View) ScrollbarColor(hover, pressed bool) color.Color
- func (v *View) SetBounds(r image.Rectangle)
- func (v *View) SetScale(scale float64)
- func (v *View) SetScrollbar(on bool)
- func (v *View) SetStyleSheet(s StyleSheet)
- func (v *View) SetZoom(zoom float64)
- func (v *View) VisibleRange() (start, end float64)
- func (v *View) Zoom() float64
- type ViewOption
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AnchorClick ¶ added in v0.6.0
type AnchorClick struct {
// ID is the anchor's id, percent-decoded and without the "#", ready
// for [View.ScrollToAnchor]. It's empty for a bare "#", which
// browsers take to mean the top of the document.
ID string
}
AnchorClick is a link within the document ("#id") being clicked or tapped. A Panel scrolls to the anchor by default (see Panel.SetAnchorScrolling); a Controller only reports it.
type Controller ¶ added in v0.6.0
type Controller struct {
// contains filtered or unexported fields
}
Controller turns a backend's input events into what they do to a View: scrolling, link hovering, sideways-scrolling blocks and their scrollbars, touch pans and flings. Feed it each frame's input with Frame, which returns the Events that happened, such as a link being clicked. It also scrolls on command (ScrollDown, PageDown, ScrollLeft and so on), for an app binding keys to them.
func NewController ¶ added in v0.6.0
func NewController(v *View) *Controller
NewController returns a Controller for v, at scale 1. It acts on input inside v's Bounds.
func (*Controller) Animating ¶ added in v0.6.0
func (c *Controller) Animating() bool
Animating reports whether frames must keep coming even without input: while a fling coasts, or a scrollbar fades out. A backend whose frames are event-driven (like Gio's) must keep requesting frames while it's true, or the animation stops dead.
func (*Controller) Frame ¶ added in v0.6.0
Frame applies one frame's input events, in order, at now: elapsed time on the clock the View is drawn with (see View.Draw). Call it once per frame, with no events if there were none, so flings keep coasting.
It returns what happened that the app may want to react to, such as a LinkClick, in order; nil if nothing did. The Controller doesn't act on them itself.
A fling stops if the app moves the View itself (with View.ScrollBy, View.ScrollToAnchor and so on) or swaps it with SetView.
func (*Controller) PageDown ¶ added in v0.6.0
func (c *Controller) PageDown()
PageDown scrolls a page towards the end.
func (*Controller) PageUp ¶ added in v0.6.0
func (c *Controller) PageUp()
PageUp scrolls a page towards the start.
func (*Controller) Scale ¶ added in v0.6.0
func (c *Controller) Scale() float64
Scale returns the display's scale (see SetScale).
func (*Controller) ScrollDown ¶ added in v0.6.0
func (c *Controller) ScrollDown()
ScrollDown scrolls a step towards the end, as for an arrow key.
func (*Controller) ScrollLeft ¶ added in v0.6.0
func (c *Controller) ScrollLeft() bool
ScrollLeft scrolls a block wider than the View (a code block or table, say) a step towards its start: the block under the pointer, else the one last scrolled, clicked or touched, if it's still on screen. It reports whether there was such a block.
func (*Controller) ScrollRight ¶ added in v0.6.0
func (c *Controller) ScrollRight() bool
ScrollRight scrolls a block a step towards its end, like ScrollLeft.
func (*Controller) ScrollUp ¶ added in v0.6.0
func (c *Controller) ScrollUp()
ScrollUp scrolls a step towards the start, as for an arrow key.
func (*Controller) SetScale ¶ added in v0.6.0
func (c *Controller) SetScale(s float64)
SetScale sets the display's scale: input pixels per logical pixel, without any zoom of the document. Command scrolling steps and touch thresholds are in logical pixels, so they don't change with the zoom.
func (*Controller) SetView ¶ added in v0.6.0
func (c *Controller) SetView(v *View)
SetView makes the Controller drive v instead. Nothing stays hovered in the previous View; the next Frame hovers whatever is under the pointer in v.
func (*Controller) View ¶ added in v0.6.0
func (c *Controller) View() *View
View returns the View the Controller drives.
type Document ¶ added in v0.5.0
type Document struct {
// contains filtered or unexported fields
}
Document is a parsed Markdown document, made by Parse. It's immutable, and any number of Views can show it.
func Parse ¶
func Parse(source []byte, opts ...ParseOption) *Document
Parse compiles Markdown source into a Document ready to render with a View. Parse only builds structure: all appearance (fonts, colors, margins, ...) comes from the View's StyleSheet, so the same Document can be shown in different styles without parsing it again.
func (*Document) TOCEntries ¶ added in v0.5.0
TOCEntries returns every top-level heading in the document, in document order.
func (*Document) Title ¶ added in v0.5.0
Title returns the text of the document's first heading, at any level, or ok=false if it has none.
Only a top-level heading is found: one nested inside a blockquote or list isn't. The same holds for TOCEntries and View.ScrollToAnchor.
type Event ¶ added in v0.6.0
type Event interface {
// contains filtered or unexported methods
}
Event is something that happened in a View that an app may react to, returned by Controller.Frame and Panel.Frame: the counterpart of the input events going in. Only this package defines kinds of Event, so new kinds can be added without breaking anyone: code that doesn't know a kind ignores it.
type LinkClick ¶ added in v0.6.0
type LinkClick struct {
// Destination is the link's destination, as written in the document.
Destination string
}
LinkClick is a link to elsewhere than the document itself being clicked or tapped. Following it, such as loading another document, is up to the app.
type Panel ¶ added in v0.5.0
type Panel struct {
// contains filtered or unexported fields
}
Panel shows a View in a rectangle of a window and makes it interactive: it lays the View out to fit, draws it there, and turns input into scrolling, hovering and clicking (through a Controller). It keeps its settings when the View is swapped, so an app can show one document after another in the same place.
A Panel doesn't depend on a graphics library. Each frame, the app passes it the frame's input events (from a backend's input.Source) and a canvas.Canvas to draw on, along with the time.
Unlike a Controller, a Panel acts on some Events itself: it follows links within the document (see SetAnchorScrolling).
func NewPanel ¶ added in v0.6.0
NewPanel returns a Panel showing view in bounds, at scale 1 and zoom 1. bounds is in canvas coordinates (see Coordinates in the package documentation).
func (*Panel) Animating ¶ added in v0.6.0
Animating reports whether the Panel needs more frames even without input: a fling is coasting, or a scrollbar is fading.
func (*Panel) Draw ¶ added in v0.6.0
Draw draws the View onto dst, within the Panel's bounds, as it is at now.
func (*Panel) Frame ¶ added in v0.6.0
Frame applies one frame's input events at now, elapsed time on the app's clock, and returns what happened, like Controller.Frame. Call it once per frame, before Draw, with no events if there were none, so flings keep coasting.
Unless SetAnchorScrolling turned it off, an AnchorClick has already scrolled the View to its anchor by the time Frame returns it.
func (*Panel) PageDown ¶ added in v0.5.0
func (p *Panel) PageDown()
PageDown scrolls a page towards the end.
func (*Panel) PageUp ¶ added in v0.5.0
func (p *Panel) PageUp()
PageUp scrolls a page towards the start.
func (*Panel) ScrollDown ¶ added in v0.5.0
func (p *Panel) ScrollDown()
ScrollDown scrolls a step towards the end, as for an arrow key.
func (*Panel) ScrollLeft ¶ added in v0.6.0
ScrollLeft scrolls a block wider than the View a step towards its start (see Controller.ScrollLeft), reporting whether there was one.
func (*Panel) ScrollRight ¶ added in v0.6.0
ScrollRight scrolls a block wider than the View a step towards its end, like ScrollLeft.
func (*Panel) ScrollUp ¶ added in v0.5.0
func (p *Panel) ScrollUp()
ScrollUp scrolls a step towards the start, as for an arrow key.
func (*Panel) SetAnchorScrolling ¶ added in v0.6.0
SetAnchorScrolling sets whether a link within the document ("#id") scrolls the View to its anchor, as it does by default. Turn it off to handle AnchorClick events differently, e.g. to record history first.
func (*Panel) SetScale ¶ added in v0.5.0
SetScale sets the display's scale: canvas pixels per logical pixel.
func (*Panel) SetScrollbar ¶ added in v0.6.0
SetScrollbar shows or hides the View's own scrollbar (see WithScrollbar), in the current View and, when on, in every View the Panel shows after it.
func (*Panel) SetStyleSheet ¶ added in v0.5.0
func (p *Panel) SetStyleSheet(s StyleSheet)
SetStyleSheet sets the StyleSheet of the current View and of every View the Panel shows after it.
func (*Panel) SetView ¶ added in v0.5.0
SetView shows v instead, with the Panel's bounds, scale, zoom, StyleSheet and scrollbar, if set, so it can be scrolled straight away.
func (*Panel) SetZoom ¶ added in v0.6.0
SetZoom magnifies the document by zoom (1 is 100%), in the current View and every View the Panel shows after it (see View.SetZoom). Scrolling steps don't change with the zoom.
type ParseOption ¶ added in v0.3.0
type ParseOption func(*parseOptions)
ParseOption customizes Parse - see WithCodeBlockPlugin.
func WithCodeBlockPlugin ¶ added in v0.5.0
func WithCodeBlockPlugin(p codeblocks.Plugin) ParseOption
WithCodeBlockPlugin registers a plugin that parses fenced code blocks in the languages it handles, e.g. to color them or render them as diagrams. Call it once per plugin: plugins are tried in registration order (see codeblocks.Plugin).
type ScrollPosition ¶
type ScrollPosition struct {
// contains filtered or unexported fields
}
ScrollPosition is an opaque snapshot of a View's scroll position, captured by ScrollPosition and restored by RestoreScrollPosition.
type StyleSheet ¶
type StyleSheet interface {
// Styles is for whynot's own use. Its result type is internal, so a
// StyleSheet can only be made by packages in this module.
Styles() styling.Styles
}
StyleSheet is how a document looks: an immutable, opaque value, made by the packages under styles/ (e.g. styles/simpletheme's DarkStyleSheet). A View asked for a color reads it from its StyleSheet (see View.HighlightColor, View.ScrollbarColor).
type TOCEntry ¶ added in v0.5.0
type TOCEntry struct {
ID string // the heading's anchor id - what View.ScrollToAnchor takes
Level int // 1-6
Text string
}
TOCEntry is one heading of a Document - enough to build a table of contents entry linking to ID.
type View ¶
type View struct {
// contains filtered or unexported fields
}
View renders a Document into a rectangle of a Canvas, its Bounds, scrolled to a position. It lays out only what's needed to draw, lays out again only when the width, scale or StyleSheet change, and keeps the scroll position across those changes.
A View reads no input itself: a Controller turns input into hovering, clicking and scrolling. Its own methods are for programmatic use: SetBounds, SetScale and SetZoom when the window, screen or zoom change, and positioning with ScrollBy, ScrollToRatio, ScrollToAnchor and RestoreScrollPosition.
All its positions and distances are in canvas pixels (see Coordinates in the package documentation).
func NewView ¶
func NewView(doc *Document, faceSelector fonts.FaceSelector, styleSheet StyleSheet, opts ...ViewOption) *View
NewView returns a View of doc (see Parse), drawn with faceSelector's fonts in styleSheet's style (e.g. simpletheme.DarkStyleSheet), at scale 1 and zoom 1. It has empty bounds, so it shows nothing until SetBounds is called.
func (*View) CurrentHeadingID ¶ added in v0.5.0
CurrentHeadingID returns the id of the top-level heading at or just above the top of the viewport - the section currently on screen - or ok=false if there's none before the scroll position, or nothing has been laid out yet.
func (*View) Draw ¶
Draw draws the View onto dst, within its Bounds, as it is at now: elapsed time on a clock of the caller's choosing (any origin, as long as it's the same on every call), which animated images and fading scrollbars follow. Call it every frame: it also picks up images that have finished loading.
Draw fills its Bounds with the StyleSheet's background color first, so a caller doesn't need its own clear step. Its cost follows what's visible, not the document's size or how far into it the scroll position is.
func (*View) HighlightColor ¶ added in v0.6.0
HighlightColor is the color the View's StyleSheet shows a hovered link in - e.g. for an app echoing the link's destination elsewhere, in the same color.
func (*View) HitTest ¶
HitTest returns the rectangle of the content at (x, y), e.g. for drawing an outline around it. ok is false if (x, y) is outside the Bounds, or doesn't land on any content: past the end of the document, or in a margin or gap.
func (*View) HoveredLink ¶ added in v0.6.0
HoveredLink returns the destination of the link under the pointer, as written in the document, or ok=false if there's none. A Controller keeps it up to date; it's highlighted in the StyleSheet's HighlightColor.
func (*View) LinkAt ¶
LinkAt reports the destination URL of the link at (x, y). ok is false if (x, y) doesn't land on a link.
func (*View) RestoreScrollPosition ¶
func (v *View) RestoreScrollPosition(p ScrollPosition)
RestoreScrollPosition restores a position captured earlier by ScrollPosition - only meaningful on the same View it was taken from.
func (*View) ScrollBy ¶ added in v0.6.0
ScrollBy moves the scroll position dy pixels towards the end of the document (towards the start if dy is negative).
func (*View) ScrollPosition ¶
func (v *View) ScrollPosition() ScrollPosition
ScrollPosition captures the View's current scroll position.
func (*View) ScrollToAnchor ¶
ScrollToAnchor scrolls to put the heading with the given anchor id at the top of the viewport, e.g. after following a link with a URL fragment. ok is false, and the scroll position unchanged, if no heading has that id or nothing has been laid out yet.
Only top-level headings are found: not one nested in a blockquote or list.
func (*View) ScrollToRatio ¶
ScrollToRatio puts the top of the View at ratio (clamped to [0, 1]) of the document's estimated height, e.g. while dragging a scrollbar thumb (VisibleRange gives the ratio back).
func (*View) ScrollbarColor ¶ added in v0.6.0
ScrollbarColor is the color the View's StyleSheet gives a scrollbar thumb: hover whenever it's highlighted (including while dragged), pressed only while dragged - for a backend drawing the View's scrollbar.
func (*View) SetBounds ¶ added in v0.6.0
SetBounds sets where the View is drawn on the canvas, which is also where its HitTest and LinkAt apply. A change of width lays the document out again, keeping the scroll position.
func (*View) SetScale ¶ added in v0.6.0
SetScale sets the display's scale: canvas pixels per logical pixel, so that text and margins are sized for the screen's density. The document is laid out at the scale times the zoom (see SetZoom): fonts at that times 72 DPI, and the StyleSheet's dimensions multiplied by it. A change lays the document out again, keeping the scroll position.
func (*View) SetScrollbar ¶ added in v0.6.0
SetScrollbar shows or hides the View's own vertical scrollbar (see WithScrollbar).
func (*View) SetStyleSheet ¶
func (v *View) SetStyleSheet(s StyleSheet)
SetStyleSheet swaps the View's StyleSheet and takes effect immediately: style values are resolved when the layout is built, so it's rebuilt here, re-anchoring the scroll position the same way a resize does. If nothing has been laid out yet, SetBounds lays it out with s.
func (*View) SetZoom ¶ added in v0.6.0
SetZoom magnifies the document by zoom (1 is 100%), on top of the display's scale (see SetScale). A change lays the document out again, keeping the scroll position.
func (*View) VisibleRange ¶ added in v0.6.0
VisibleRange returns the part of the document in view, as fractions of its height: from start to end, with 0 <= start <= end <= 1 - e.g. for drawing a scrollbar thumb. ScrollToRatio(start) is the way back. The height is an estimate until the whole document has been laid out, so the fractions can shift a little as more of it is seen. Before anything is laid out, it's (0, 1).
type ViewOption ¶
type ViewOption func(*View)
ViewOption customizes a View at construction, via NewView's opts parameter.
func WithImageSource ¶
func WithImageSource(s images.Source) ViewOption
WithImageSource sets where the View's images come from, instead of the default images.FileSource - e.g. relative to the document's location, or over http(s). Each image is fetched at most once per View.
func WithScrollbar ¶ added in v0.6.0
func WithScrollbar() ViewOption
WithScrollbar shows the View's own vertical scrollbar, drawn along its right edge as its StyleSheet says, whenever the document is taller than the View. A Controller lets the user drag it.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
backends
|
|
|
ebitenbackend
Package ebitenbackend is whynot's backend for Ebitengine (github.com/hajimehoshi/ebiten/v2).
|
Package ebitenbackend is whynot's backend for Ebitengine (github.com/hajimehoshi/ebiten/v2). |
|
giobackend
module
|
|
|
Package canvas is the drawing contract between whynot and a graphics framework.
|
Package canvas is the drawing contract between whynot and a graphics framework. |
|
cmd
|
|
|
whynot
command
|
|
|
Package codeblocks is the contract between whynot's Markdown compiler and code-block plugins, which change how fenced code blocks are shown.
|
Package codeblocks is the contract between whynot's Markdown compiler and code-block plugins, which change how fenced code blocks are shown. |
|
chromahighlight
Package chromahighlight is a code-block plugin (codeblocks.Plugin) that highlights code in every language the chroma library (github.com/alecthomas/chroma) knows: a fenced code block's source is split into tokens classed as keywords, types, strings and so on, which the stylesheet colors.
|
Package chromahighlight is a code-block plugin (codeblocks.Plugin) that highlights code in every language the chroma library (github.com/alecthomas/chroma) knows: a fenced code block's source is split into tokens classed as keywords, types, strings and so on, which the stylesheet colors. |
|
kroki
Package kroki is a code-block plugin that shows diagrams as images: a fenced code block in a diagram language is sent to Kroki (https://kroki.io), a service that renders diagrams, and shown as the picture it returns.
|
Package kroki is a code-block plugin that shows diagrams as images: a fenced code block in a diagram language is sent to Kroki (https://kroki.io), a service that renders diagrams, and shown as the picture it returns. |
|
examples
|
|
|
chromahighlight
command
Command chromahighlight is a runnable example of a code-block plugin: chromahighlight.Plugin (github.com/alecthomas/chroma/v2) coloring code.
|
Command chromahighlight is a runnable example of a code-block plugin: chromahighlight.Plugin (github.com/alecthomas/chroma/v2) coloring code. |
|
customfont
command
Command customfont is a runnable example of fonts.CustomSelector.
|
Command customfont is a runnable example of fonts.CustomSelector. |
|
panel
command
Command panel is a runnable example of a whynot.Panel embedded in a larger Ebitengine game window: it fills the whole window with a solid color standing in for "other game content," then draws a Panel into an inset rectangle, showing its drawing stays within its bounds on all four edges.
|
Command panel is a runnable example of a whynot.Panel embedded in a larger Ebitengine game window: it fills the whole window with a solid color standing in for "other game content," then draws a Panel into an inset rectangle, showing its drawing stays within its bounds on all four edges. |
|
systemfont
command
Command systemfont is a runnable example of systemfont.Selector.
|
Command systemfont is a runnable example of systemfont.Selector. |
|
view
command
Command view is a runnable example of whynot.View wired up by hand - full control over input handling, at the cost of doing it yourself.
|
Command view is a runnable example of whynot.View wired up by hand - full control over input handling, at the cost of doing it yourself. |
|
wasm
command
Command wasm is a runnable example of whynot compiled to WebAssembly and run in a browser, via Ebitengine's own js/wasm backend - see README.md in this directory for how to build and serve it.
|
Command wasm is a runnable example of whynot compiled to WebAssembly and run in a browser, via Ebitengine's own js/wasm backend - see README.md in this directory for how to build and serve it. |
|
Package fonts is how whynot gets the fonts it draws text with.
|
Package fonts is how whynot gets the fonts it draws text with. |
|
systemfont
Package systemfont is a fonts.FaceSelector for the fonts installed on the system.
|
Package systemfont is a fonts.FaceSelector for the fonts installed on the system. |
|
Package images is how whynot gets the images a document shows.
|
Package images is how whynot gets the images a document shows. |
|
Package input is the contract between a backend's input and whynot.
|
Package input is the contract between a backend's input and whynot. |
|
internal
|
|
|
ast
Package ast is the semantic tree of a whynot document: what each element is (its Tag), how elements nest, and the few facts about them the engine needs, like a heading's anchor ID or a link's destination.
|
Package ast is the semantic tree of a whynot document: what each element is (its Tag), how elements nest, and the few facts about them the engine needs, like a heading's anchor ID or a link's destination. |
|
browser
Package browser is the backend-agnostic half of a whynot document browser: navigation history, the current theme/zoom, document/image loading, the welcome page, and toolbar icons - everything cmd/whynot needs that isn't specific to ebiten, shaped so a Gio-based app can use it too.
|
Package browser is the backend-agnostic half of a whynot document browser: navigation history, the current theme/zoom, document/image loading, the welcome page, and toolbar icons - everything cmd/whynot needs that isn't specific to ebiten, shaped so a Gio-based app can use it too. |
|
canvastest
Package canvastest provides a canvas.Canvas fake for tests: Recorder records each draw call instead of drawing.
|
Package canvastest provides a canvas.Canvas fake for tests: Recorder records each draw call instead of drawing. |
|
engine
Package engine is the pipeline from a document's blocks to pixels: it turns the block and inline tree the compiler builds into layout boxes, and draws and hit-tests them on a canvas.Canvas.
|
Package engine is the pipeline from a document's blocks to pixels: it turns the block and inline tree the compiler builds into layout boxes, and draws and hit-tests them on a canvas.Canvas. |
|
imagecache
Package imagecache loads the images a document shows through an images.Source: an asynchronous cache that fetches and decodes each image once, and decoding of animated GIFs.
|
Package imagecache loads the images a document shows through an images.Source: an asynchronous cache that fetches and decodes each image once, and decoding of animated GIFs. |
|
markdown
Package markdown is whynot's Markdown compiler: it parses source with goldmark and builds the engine's block and inline tree, alongside the semantic ast.Node tree they refer to (Compile).
|
Package markdown is whynot's Markdown compiler: it parses source with goldmark and builds the engine's block and inline tree, alongside the semantic ast.Node tree they refer to (Compile). |
|
styling
Package styling is whynot's style machinery: the per-element queries the layout engine resolves appearance through (Styles), and the field-configured implementation simpletheme builds (Basic).
|
Package styling is whynot's style machinery: the per-element queries the layout engine resolves appearance through (Styles), and the field-configured implementation simpletheme builds (Basic). |
|
styling/stylingtest
Package stylingtest provides styles for tests of packages that can't import a theme package (whynot's own tests: styles/...
|
Package stylingtest provides styles for tests of packages that can't import a theme package (whynot's own tests: styles/... |
|
styles
|
|
|
simpletheme
Package simpletheme makes stylesheets (whynot.StyleSheet) from a fixed set of fields: margins, text styles and colors for each kind of Markdown element, plus the scrollbars and the colors of highlighted code.
|
Package simpletheme makes stylesheets (whynot.StyleSheet) from a fixed set of fields: margins, text styles and colors for each kind of Markdown element, plus the scrollbars and the colors of highlighted code. |
