Package styling implements XEP-0393: Message Styling, a simple styling language.

This package does not convert message styling documents into a format usable by any other rendering engine (ie. HTML or LaTeX), instead it tokenizes the input and provides you with a bitmask of styles that should be applied to each token.


Message Styling borrows several familiar formatting options from Markdown (though it is much simpler and not compatible with Markdown parsers).

Several inline formats exist:

A string wrapped in _emph_ should be displayed emphasized (normally in italics), and strings wrapped in *strong* will have strong emphasis (normally bold). The `pre` styling directive results in an inline pre-formatted string (monospace with no child formatting allowed), and the ~strike~ style should result in text with a line through the middle (strike through).

There are also a few block formats such as a block quotation:

> A quotation
>> Can be multi-level

And a preformatted text block which can have no child blocks, should be displayed in a monospace font, and which should not be re-wrapped:

```an optional tag may go here.
Lines of pre-formatted text go here.
Example (Html)


package main

import (

func main() {
	r := strings.NewReader(`The full title is
_Twelfth Night, or What You Will_
but *most* people shorten it.`)
	d := styling.NewDecoder(r)

	var out strings.Builder
	out.WriteString("<!doctype HTML>\n")
	for {
		tok, err := d.Token()
		if err == io.EOF {
		if err != nil {
			out.WriteString(html.EscapeString(fmt.Sprintf("Error encountered while parsing tokens: %v", err)))

		switch {
		case tok.Mask&styling.SpanEmphStart == styling.SpanEmphStart:
		case tok.Mask&styling.SpanStrongStart == styling.SpanStrongStart:
		case tok.Mask&styling.SpanEmphEnd == styling.SpanEmphEnd:
		case tok.Mask&styling.SpanStrongEnd == styling.SpanStrongEnd:
			// TODO: no other styles implemented to keep the example short.

<!doctype HTML>
The full title is
<em><code>_</code>Twelfth Night, or What You Will<code>_</code></em>
but <strong><code>*</code>most<code>*</code></strong> people shorten it.




const (
	// BlockPre represents a preformatted text block.
	// It should be displayed in a monospace font with no change to line breaks.
	BlockPre Style = 1 << iota

	// BlockQuote represents a nestable quotation.
	// To get the level of the quotation see the Quote method.

	// SpanEmph is an inline span of text that should be displayed in italics.

	// SpanStrong is an inline span of text that should be displayed bold.

	// SpanStrike is an inline span of text that should be displayed with a
	// horizontal line through the middle (strike through).

	// SpanPre is an inline span of text that should be displayed in a monospace
	// font.

	// Styling directive markers.
	// It is often desirable to distinguish the characters that triggered styling
	// from surrounding text. These bits are set only on styling directives, the
	// characters or sequences of characters that result in the style changing.
	// The corresponding style bit will also be set whenever the start or end bits
	// are set. For example, in *strong* the first "*" will have
	// SpanStrong|SpanStrongStart set, the "strong" will only have SpanStrong set,
	// and the last "*" will have SpanStrong|SpanStrongEnd set.

	// Various useful masks
	// These bitmasks are provided as a convenience to make it easy to check what
	// general category of styles are applied.
	Block               = BlockPre | BlockQuote
	Span                = SpanEmph | SpanStrong | SpanStrike | SpanPre
	SpanEmphDirective   = SpanEmphStart | SpanEmphEnd
	SpanStrongDirective = SpanStrongStart | SpanStrongEnd
	SpanStrikeDirective = SpanStrikeStart | SpanStrikeEnd
	SpanPreDirective    = SpanPreStart | SpanPreEnd
	SpanDirective       = SpanEmphDirective | SpanStrongDirective | SpanStrikeDirective | SpanPreDirective
	SpanStartDirective  = SpanEmphStart | SpanStrongStart | SpanStrikeStart | SpanPreStart
	SpanEndDirective    = SpanEmphEnd | SpanStrongEnd | SpanStrikeEnd | SpanPreEnd
	BlockPreDirective   = BlockPreStart | BlockPreEnd
	BlockQuoteDirective = BlockQuoteStart | BlockQuoteEnd
	BlockDirective      = BlockPreDirective | BlockQuoteDirective
	BlockStartDirective = BlockPreStart | BlockQuoteStart
	BlockEndDirective   = BlockPreEnd | BlockQuoteEnd
	Directive           = SpanDirective | BlockDirective
	StartDirective      = SpanStartDirective | BlockStartDirective
	EndDirective        = SpanEndDirective | BlockEndDirective

The style bits.


This section is empty.


func Scan

func Scan() bufio.SplitFunc

Scan returns a new stateful split function for a bufio.Scanner that splits on message styling tokens. This function is different from a Decoder in that it will not return block quote end tokens.

This is a low-level building block of this package. Most users will want to use a Decoder instead.


type Decoder

type Decoder struct {
	// contains filtered or unexported fields

A Decoder represents a styling lexer reading a particular input stream. The parser assumes that input is encoded in UTF-8.

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder creates a new styling parser reading from r. If r does not implement io.ByteReader, NewDecoder will do its own buffering.

func (*Decoder) Quote

func (d *Decoder) Quote() uint

Quote is the blockquote depth at the current position in the document.

func (*Decoder) SkipBlock

func (d *Decoder) SkipBlock() error

SkipBlock pops tokens from the decoder until it reaches the end of the current block, positioning the token stream at the beginning of the next block. It returns any errors it encounters along the way. If SkipBlock is called at the beginning of the input stream before any tokens have been popped or any blocks have been entered, it will skip the entire input stream as if everything were contained in an imaginary "root" block.

func (*Decoder) SkipSpan

func (d *Decoder) SkipSpan() error

SkipSpan pops tokens from the decoder until it reaches the end of the current span, positioning the token stream at the beginning of the next span or block. If SkipSpan is called while no span is entered it behaves like SkipBlock. It returns any errors it encounters along the way.

func (*Decoder) Style

func (d *Decoder) Style() Style

Style returns a bitmask representing the currently applied styles at the current position in the document.

func (*Decoder) Token

func (d *Decoder) Token() (Token, error)

Token returns the next styling token in the input stream. At the end of the input stream, it returns an empty token and io.EOF. Returned tokens do not always correspond directly to the input stream. For example, at the end of a block quote an empty token is returned with the mask BlockQuote|BlockQuoteEnd, but there is no explicit block quote terminator character in the input stream so its data will be empty.

Slices of bytes in the returned token data refer to the parser's internal buffer and remain valid only until the next call to Token. To acquire a copy of the bytes call the token's Copy method.

type Style

type Style uint32

Style is a bitmask that represents a set of styles that can be applied to text.

type Token

type Token struct {
	Mask Style
	Data []byte
	Info []byte

A Token represents a styling directive or unstyled span of text. If the token is a preformatted text block start token, Info is a slice of the bytes between the code fence (```) and the newline.

func (Token) Copy

func (t Token) Copy() Token

Copy creates a new copy of the token.

Source Files