Help us shape the future of Go! Take the 2026 Go Developer Survey

common

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package common holds what the diagrams share beyond layout and drawing, as Pele's diagrams/common does:

  • fitting a diagram to the width the host has (Tighten, TurnToFit, FitWidth), and the curve the host's routing asks for (RoutingCurve);
  • laying out labels: plain and fitted ones (fit.go), text cut to fit a room and one-line labels (fittext.go: FitText, Line, LineOf), labels taken literally (literallabel.go), and a diagram's title (title.go);
  • reading generic types (generics.go) and class lists (classes.go: ClassNames, TrimDefault);
  • the icons a host can draw, and the glyphs drawn for them (icons.go);
  • the lexer and reader of the Langium grammars, with the token types they share (tokens.go: Tokenize, Reader, Keyword, AccDescr and the rest);
  • the scanning helpers of the hand-written Jison lexers (scan.go: KeywordAt, WordAt, Accessibility and the rest);
  • the indented outlines of kanban boards and mindmaps (outline.go);
  • the errors of diagrams' text, as Pele's src/errors.ts makes them (errors.go: NewError, SyntaxError, Locate).

Index

Constants

View Source
const (
	TokEnd = iota
	TokError
	TokSpaceLine
	TokNL
	TokEOF
	TokKeyword
	TokSpaceList
	TokIcon
	TokClass
	TokNodeDStart
	TokNodeID
	TokNodeDescr
	TokNodeDEnd
	TokShapeData
)

The outline's tokens, Pele's T.

View Source
const (
	NodeDefault     = 0
	NodeRoundedRect = 1
	NodeRect        = 2
	NodeCircle      = 3
	NodeCloud       = 4
	NodeBang        = 5
	NodeHexagon     = 6
)

The shapes of a node, Pele's NODE_TYPE.

View Source
const GlyphStroke = 1.5

GlyphStroke is how wide Pele strokes a glyph it draws itself, in units of its grid.

Variables

View Source
var AccDescrToken = TokenType{Name: "ACC_DESCR", First: "\t a", Match: func(s string, at int) int {
	i := blanks(s, at)
	if !strings.HasPrefix(s[i:], "accDescr") {
		return -1
	}
	i += len("accDescr")
	if j := blanks(s, i); j < len(s) && s[j] == ':' {
		return lineRest(s, j+1)
	}
	i = chars.SpaceRun(s, i)
	if i == len(s) || s[i] != '{' {
		return -1
	}
	end := strings.IndexByte(s[i+1:], '}')
	if end < 0 {
		return -1
	}
	return i + 1 + end + 1
}}

AccDescrToken is Pele's ACC_DESCR, /[\t ]*accDescr(?:[\t ]*:([^\n\r]*?(?=%%)|[^\n\r]*)|\s*{([^}]*)})/y.

View Source
var AccTitleToken = TokenType{Name: "ACC_TITLE", First: "\t a", Match: func(s string, at int) int {
	i := blanks(s, at)
	if !strings.HasPrefix(s[i:], "accTitle") {
		return -1
	}
	i = blanks(s, i+len("accTitle"))
	if i == len(s) || s[i] != ':' {
		return -1
	}
	return lineRest(s, i+1)
}}

AccTitleToken is Pele's ACC_TITLE, /[\t ]*accTitle[\t ]*:(?:[^\n\r]*?(?=%%)|[^\n\r]*)/y.

View Source
var CommentToken = TokenType{Name: "SINGLE_LINE_COMMENT", First: "\t %", Hidden: true, Match: func(s string, at int) int {
	i := blanks(s, at)
	if !strings.HasPrefix(s[i:], "%%") {
		return -1
	}
	for i += 2; i < len(s) && s[i] != '\n' && s[i] != '\r'; i++ {
	}
	return i
}}

CommentToken is Pele's SINGLE_LINE_COMMENT, /[\t ]*%%[^\n\r]*/y, which is hidden.

View Source
var DirectiveToken = TokenType{
	Name: "DIRECTIVE", First: "\t %", Hidden: true,
	Opener: func(s string, at int) bool { return directiveOpener(s, at) >= 0 },
	Match: func(s string, at int) int {
		q := directiveOpener(s, at)
		if q < 0 {
			return -1
		}
		for k := q; k < len(s); k++ {
			if !strings.HasPrefix(s[k:], "}%%") {
				continue
			}
			if end := Closed(s, k+3); end >= 0 {
				return end
			}
		}
		return -1
	},
}

DirectiveToken is Pele's DIRECTIVE, /[\t ]*%%{[\S\s]*?}%%(?:\r?\n|(?!\S))/y, which is hidden.

View Source
var IntToken = TokenType{Name: "INT", Match: func(s string, at int) int {
	switch {
	case s[at] == '0':
		return at + 1
	case s[at] < '1' || s[at] > '9':
		return -1
	}
	end := at + 1
	for end < len(s) && chars.IsDigit(int(s[end])) {
		end++
	}
	if end < len(s) && s[end] == '.' {
		if end-1 > at {
			return end - 1
		}
		return -1
	}
	return end
}}

IntToken is the INT that packet and git diagrams define alike, /0|[1-9][0-9]*(?!\.)/y: a lone 0, or digits not followed by a dot, which give back the last digit rather than fail when they are. Pele writes it in each diagram's table.

View Source
var NewlineToken = TokenType{Name: "NEWLINE", First: "\r\n", Match: LineBreak}

NewlineToken is Pele's NEWLINE, /\r?\n/y.

View Source
var StringToken = TokenType{Name: "STRING", First: `"'`, Match: func(s string, at int) int {
	q := s[at]
	if q != '"' && q != '\'' {
		return -1
	}
	for i := at + 1; i < len(s); {
		switch s[i] {
		case q:
			return i + 1
		case '\\':
			c, size := chars.UnitAt(s, i+1)
			if c < 0 || chars.IsLineEnd(c) {
				return -1
			}
			i += 1 + size
		default:
			i++
		}
	}
	return -1
}}

StringToken is Pele's STRING, /"([^"\\]|\\.)*"|'([^'\\]|\\.)*'/y. Each character has one way to be taken, so the first quote that ends it is its end; a backslash before a line terminator, which . does not take, ends no string.

View Source
var TitleToken = TokenType{Name: "TITLE", First: "\t t", Match: func(s string, at int) int {
	i := blanks(s, at)
	if !strings.HasPrefix(s[i:], "title") {
		return -1
	}
	i += len("title")
	if i < len(s) && (s[i] == ' ' || s[i] == '\t') {
		return lineRest(s, i+1)
	}
	return i
}}

TitleToken is Pele's TITLE, /[\t ]*title(?:[\t ][^\n\r]*?(?=%%)|[\t ][^\n\r]*|)/y: the word alone matches too, so `title1` starts with a title.

View Source
var WhitespaceToken = TokenType{Name: "WHITESPACE", First: "\t ", Hidden: true, Match: func(s string, at int) int {
	if end := blanks(s, at); end > at {
		return end
	}
	return -1
}}

WhitespaceToken is Pele's WHITESPACE, /[\t ]+/y, which is hidden.

View Source
var YAMLToken = TokenType{
	Name: "YAML", First: "-", Hidden: true,
	Opener: func(s string, at int) bool { return yamlOpener(s, at) >= 0 },
	Match: func(s string, at int) int {
		q := yamlOpener(s, at)
		if q < 0 {
			return -1
		}
		for k := q; k < len(s); k++ {
			j := LineBreak(s, k)
			if j < 0 || !strings.HasPrefix(s[j:], "---") {
				continue
			}
			if end := Closed(s, j+3); end >= 0 {
				return end
			}
		}
		if strings.HasPrefix(s[q:], "---") {
			return Closed(s, q+3)
		}
		return -1
	},
}

YAMLToken is Pele's YAML, /---[\t ]*\r?\n(?:[\S\s]*?\r?\n)?---(?:\r?\n|(?!\S))/y, front matter, which is hidden. The group is tried first, so the closing dashes are the first after a line break, past any that follow the opener at once.

Functions

func AccDescrValue

func AccDescrValue(text string) string

AccDescrValue is the description of an ACC_DESCR token, as Pele's accDescrValue reads it with /accDescr(?:[\t ]*:([^\n\r]*)|\s*{([^}]*)})/: a line made single, or a block with its lines' leading and trailing white space taken off, runs of tabs and spaces made one space and runs of line breaks one line feed.

func AccTitleValue

func AccTitleValue(text string) string

AccTitleValue is the title of an ACC_TITLE token, as Pele's accTitleValue reads it with /accTitle[\t ]*:([^\n\r]*)/.

func Accessibility

func Accessibility(src string, p int, out *JisonTokens, first int) int

Accessibility lexes an accTitle or accDescr statement at byte p and returns where it ends, or p if there is none, as Pele's accessibility does. The token types acc_title, acc_title_value, acc_descr, acc_descr_value and acc_descr_multiline_value are numbered consecutively from first.

func BreakLabel

func BreakLabel(label text.Label, measure text.Measurer, room float64) text.Label

BreakLabel breaks each line of a label that is wider than room between any two characters, so that no line but one holding a single character or an icon is wider, as Pele's breakLabel does. Lines that fit are kept as they are.

func CapWidth

func CapWidth(o *layout.Options, natural, least, around float64) float64

CapWidth is the width of a chart drawn to a set width: its own, or the host's when that is smaller, with around what the chart adds outside it, as Pele's capWidth gives it.

func ClassNames

func ClassNames(raw string) []string

ClassNames is the names of a class attribute, as Pele's classNames (svg/theme.ts) cleans them: what is not an ASCII letter, a digit, an underscore or a hyphen, as /[^\w-]+/ takes it, separates them.

func Clickable

func Clickable(classes []string) (class, tags []string)

Clickable splits the classes Pele gives a node into those its author gave it and its tags: "clickable", which Mermaid adds to the classes of a node with a click, is a tag (scene.Item.Tags), and the rest are the author's, in their order.

func Closed

func Closed(s string, i int) int

Closed matches (?:\r?\n|(?!\S)) at byte i: a line break, or nothing before white space or the end of the text; -1 where neither is.

func FitLabel

func FitLabel(raw string, measure text.Measurer, size, max float64, base text.Face) text.Label

FitLabel lays out text as PlainLabel does, and for a box of fixed width also cuts any word too long to fit max, as Pele's fitLabel does: text.Layout wraps at spaces only.

func FitWidth

func FitWidth(o *layout.Options, natural, least float64, lay func(plot float64, narrow bool) *scene.Scene) *scene.Scene

FitWidth lays out a chart whose plot can be any width so that the whole of it fits the width the host has, as Pele's fitWidth does: what surrounds the plot is only known once it is laid out, so the plot gives up the overflow and is laid out again, at most three times more. narrow tells the chart it did not fit at its own width.

func Glyph

func Glyph(role scene.Role, name, id string, outline *scene.Path, box scene.Rect, stroke style.Paint) *scene.Item

Glyph is the item of a glyph a diagram draws itself, in the square box: its outline scaled from its grid to the box and stroked round in the paint given, as Pele strokes the path data it writes in place of an icon the host does not draw. id is that of the item the glyph is the icon of.

func Glyphs

func Glyphs(outlines map[string]string) map[string]*scene.Path

Glyphs reads the outlines of the glyphs a diagram draws itself, as SVG path data on a 24 by 24 grid, into paths.

func HostIcon

func HostIcon(o *layout.Options, name string) bool

HostIcon reports whether the host draws the icon of a name, as Pele asks its options' icons for one: by the name with its entities decoded.

func KeywordAt

func KeywordAt(src string, p int, word string) bool

KeywordAt reports whether word, in lowercase ASCII letters, is at byte p in any case, as Pele's keywordAt does: the grammars are case-insensitive.

func Line

func Line(s string, width, size float64, face text.Face) *text.Label

Line is a label of one line of plain text, as wide as it was measured, in a size and face of type, a line of Pele's height for the size: text Pele writes as it is, with no markup read, as a tick, a value or a name.

func LineBreak

func LineBreak(s string, i int) int

LineBreak matches \r?\n at byte i, or gives -1.

func LineEnd

func LineEnd(src string, from int) int

LineEnd is where the line that byte from is on ends, as Pele's lineEnd finds it.

func LineOf

func LineOf(s string, width, size, lineHeight float64, face text.Face) *text.Label

LineOf is Line with a line height of its own.

func LiteralLabel

func LiteralLabel(s string, measure text.Measurer, size, room float64, face text.Face) text.Label

LiteralLabel lays out text that must keep every character but the spaces its lines break at, as a filename or a field of a protocol, as Pele's literalLabel does: a line breaks at the last space that lets it fit room, or, in a word longer than that, between any two characters. Nothing in it is read as markup or entities.

func NewError

func NewError(message string, code diagram.Code, typ diagram.Type) *diagram.Error

NewError is an error with no place.

func OutlineType

func OutlineType(start, end string) int

OutlineType is the shape a node's delimiters give it, as Pele's getType does: any opening delimiter pairs with any closing one, as in Mermaid.

func ParseGenericTypes

func ParseGenericTypes(input string) string

ParseGenericTypes turns `List~int~` into `List<int>`, with the quirks of Mermaid's parseGenericTypes around commas, as Pele's parseGenericTypes does. Tildes are ASCII, so the work is done on bytes.

func ParseOutline

func ParseOutline(src string, db OutlineDB, kanban bool) error

ParseOutline makes the calls on db that the grammar's actions make, in the same order, and reports errors in the state where the generated parser would, as Pele's parseOutline does.

func PlainLabel

func PlainLabel(raw string, measure text.Measurer, size, max float64, base text.Face) text.Label

PlainLabel lays out text as plain text in which only <br> is markup, so that other tags and icon names show as written instead of being read as formatting, as Pele's plainLabel does: a < that starts no <br> is written &lt;, as /<(?!br\s*\/?>)/gi replaces it, and :fa- is written &colon;fa-. Text wraps at max even where that is 0 or less, as a box that has no room left gives it.

func RoutingCurve

func RoutingCurve(r layout.Routing) string

RoutingCurve is the curve, by Mermaid's name, that the host's routing asks edges to be drawn with: "step" for layout.Orthogonal, "linear" for layout.Straight, and "" for layout.Auto, which leaves the diagram's own curve. Pele has no such setting; it is limu's.

func RunsAcross

func RunsAcross(dir string) bool

RunsAcross reports whether a direction runs across, as Pele's runsAcross does.

func SkipTrivia

func SkipTrivia(src string, from int) int

SkipTrivia skips comments and white space, as Pele's skipTrivia does. It stops at a line break that starts a token, which is a NEWLINE. Jison compiles `\%%` to a single `%`, so one percent sign starts a comment, and the second comment rule takes any character before `%%` with it, a line break included.

func StringValue

func StringValue(text string) string

StringValue is the text of a STRING token, as Pele's stringValue reads it: the quotes taken off, and each backslash with the character after it made that character, or the control character \b, \f, \n, \r, \t, \v or \0 names.

func SyntaxError

func SyntaxError(typ diagram.Type, src string, offset int, detail string, lexical bool) *diagram.Error

SyntaxError is the error of text that does not parse at byte offset, worded as Jison's parsers word it, as Pele's syntaxError does. A lexical error is text no token starts with.

func Tighten

func Tighten(o *layout.Options, lay func(tight bool) *scene.Scene) *scene.Scene

Tighten lays a diagram out with room to spare, and tightly instead when that does not fit the width the host has and tight is narrower, as Pele's tighten does.

func TitleRoom

func TitleRoom(o *layout.Options) float64

TitleRoom is the width a title may take before it wraps, as Pele's titleRoom gives it.

func TitleValue

func TitleValue(text string) string

TitleValue is the title of a TITLE token, as Pele's titleValue reads it with /title([\t ][^\n\r]*|)/: what follows the word, which the token holds to one line.

func TrimDefault

func TrimDefault(classes string) string

TrimDefault takes /^default\s?/ off the classes of a node, as Pele does before it writes them: the class Mermaid gives every node, and the space after it.

func TurnToFit

func TurnToFit(o *layout.Options, lay func(down bool) *scene.Scene) *scene.Scene

TurnToFit lays a diagram out across, and down instead when the host allows it, the width it has is under the breakpoint, across does not fit, and down is narrower, as Pele's turnToFit does.

func WithTitle

func WithTitle(sc *scene.Scene, title string, role scene.Role, measure text.Measurer, size, pad float64)

WithTitle puts a title above a scene that was laid out without one, as Pele's withTitle does: the scene grows to hold it, what was in it moves down below it, and across to stay centered where the title is the wider, and the title is pad under the top. The title is an item of the role given.

func WordAt

func WordAt(src string, at int, word string) bool

WordAt reports whether word, written in lower case, is at byte at of src, as Pele's wordAt (common/caseless.ts) does: only ASCII letters match in either case, as with the i flag on a regular expression without the u flag. KeywordAt folds any character with |32, which would take a carriage return for the dash of x-axis.

Types

type Fitted

type Fitted struct {
	Text  string
	Size  float64
	Width float64
}

Fitted is one line of text fitted into a width, Pele's Fitted: the text, perhaps cut short, the size of type it is written in, and its width.

func FitText

func FitText(s string, room, size, least float64, measure text.Measurer, face text.Face) (Fitted, bool)

FitText fits one line of text into a width, as Pele's fitText does: first by shrinking the type down to least, then by cutting the text and adding an ellipsis. It reports false when not even one character fits.

type JisonTokens

type JisonTokens struct {
	Types  []int
	Texts  []string
	Starts []int
}

JisonTokens are the tokens of a lexer ported from Jison, the Tokens of Pele's scan.ts: the type of each token, its text, and the byte it starts at.

func (*JisonTokens) Emit

func (t *JisonTokens) Emit(typ int, src string, start, end int)

Emit adds a token of type typ that runs from byte start to byte end of src.

type Location

type Location struct {
	Line    int
	Column  int
	Snippet string
}

Location is a place in a text: its line and column, counted from 1, and its line with a caret under the column.

func Locate

func Locate(src string, offset int) Location

Locate finds the place of byte offset in src, as Pele's locate finds that of a code unit: the column is counted in UTF-16 code units.

type OutlineDB

type OutlineDB interface {
	GetType(start, end string) int
	AddNode(level int, id, descr string, typ int, shapeData string, hasData bool) error
	// DecorateNode is given an icon or, when class is set, a class.
	DecorateNode(text string, class bool)
}

OutlineDB is what the outline's parser builds, Pele's OutlineDb. shapeData is the text of a metadata block, if hasData.

type OutlineTokens

type OutlineTokens struct {
	Types  []int
	Texts  []string
	Starts []int
}

OutlineTokens are an outline's tokens, Pele's Tokens: their types, their texts, and the byte offsets they start at.

func TokenizeOutline

func TokenizeOutline(src string, kanban bool) OutlineTokens

TokenizeOutline reads an outline's tokens, as Pele's tokenize does.

type Reader

type Reader struct {
	I       int
	Tokens  *Tokens
	Types   []TokenType
	Diagram diagram.Type
}

A Reader reads tokens for a hand-written parser, as Pele's Reader does, with Chevrotain's messages on failure. Its failures panic with a *diagram.Error, which the parser recovers.

func (*Reader) Accept

func (r *Reader) Accept(kind int) bool

Accept reads the token if it is of a kind, and reports whether it was.

func (*Reader) Expect

func (r *Reader) Expect(kind int) string

Expect reads the token, which must be of a kind, and gives its text.

func (*Reader) Fail

func (r *Reader) Fail(expected string)

Fail panics with a syntax error at the token: what was expected, and what was found.

func (*Reader) Kind

func (r *Reader) Kind() int

Kind is the kind of the token being read.

func (*Reader) Take

func (r *Reader) Take() string

Take reads the token and gives its text.

func (*Reader) Text

func (r *Reader) Text(i int) string

Text is the text of token i.

type Table

type Table struct {
	Types []TokenType
	// contains filtered or unexported fields
}

A Table is a table of token types made ready to tokenize with, as Pele's prepare makes it: the types, and those that can start with each ASCII character, in matching order.

func Prepare

func Prepare(types []TokenType) *Table

Prepare makes a table of token types ready to tokenize with, as Pele's prepare does.

type TokenType

type TokenType struct {
	Name    string
	Literal string
	Match   func(src string, at int) int
	// Scanner makes a matcher that answers as Match would, for a pattern that could rescan
	// the text, as Pele's scanner does: it is called once for each text tokenized, so the
	// matcher may remember what it has scanned. A type with a Scanner needs no Match.
	Scanner func() func(src string, at int) int
	// Opener reports whether the start of a construct that needs a closer is at a byte. When
	// it is but the whole type does not match, no closer is in the rest of the text, and the
	// type is not tried again.
	Opener func(src string, at int) bool
	// First is every ASCII character a match can start with, or "" when that is not known.
	// A type with a First is tried only at those characters and at characters outside ASCII.
	First  string
	Hidden bool
	// Longer are Chevrotain's LONGER_ALT, by index in the table: when this type matches,
	// these are tried at the same place, and the first that matches more text becomes the
	// token.
	Longer []int
}

A TokenType is Pele's TokenType. A type matches its Literal, or, without one, by Match, which gives the end of the match at a byte of the text, or -1: Pele's pattern, when that is a regular expression, or its match.

func AccDescr

func AccDescr(name string) TokenType

AccDescr is Pele's accDescr(name) (common/accDescr.ts): ACC_DESCR under the name given, for grammars where lexing goes on after an `accDescr {` that never closes, because accDescr is also a name there. It matches what AccDescrToken does, but once the braced form finds no closing brace there is none further on, so later braced descriptions fail without scanning the rest of the text again.

func Keyword

func Keyword(word string) TokenType

Keyword is Pele's keyword: the word, ended only by white space, a comment or the end of the text, (?:(?=%%)|(?!\S)).

type Tokens

type Tokens struct {
	Kinds, Starts, Ends []int
	Src                 string
}

Tokens are Pele's Tokens: the kind of each token, by index in the table, and the bytes it starts and ends at, with a last of kind -1 at the end of the text.

func Tokenize

func Tokenize(src string, table *Table, typ diagram.Type) (*Tokens, error)

Tokenize splits src into tokens with the types of a table, as Pele's tokenize does. Text no type matches is a lexical error of the diagram type named.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL