asciitosvg

package module
v0.0.0-...-ca82a5c Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2020 License: MIT Imports: 12 Imported by: 1

README

ASCIIToSVG

.-------------------------.
|                         |
| .---.-. .-----. .-----. |
| | .-. | +-->  | |  <--| |
| | '-' | |  <--| +-->  | |
| '---'-' '-----' '-----' |
|  ascii     2      svg   |
|                         |
'-------------------------'

https://github.com/asciitosvg

Create beautiful SVG diagrams from ASCII art.

Introduction

License

ASCIIToSVG is copyright © 2012-2018 The ASCIIToSVG contributors, and is distributed under an MIT license. All code without explicit copyright retains this license. Any code not adhering to this license is explicit in its own copyright.

What does it do?

ASCIIToSVG is a pretty simple Go library (with an accompanying CLI tool) that parses ASCII art diagrams, attempting to convert them to an aesthetically pleasing SVG output. Someone snidely remarked in a HN thread that if you make a thing that generates visual output, show some examples of that output. Ask GitHub to support insertion of SVG into their Markdown. In the meantime, you can easily get example output by running a2s -L.

What about that other project?

The original code at https://github.com/dhobsd/asciitosvg suffers from a number of issues. It isn't particularly efficient in what's effectively a graph search problem, and its implementation in PHP leaves a bit to be desired. Some side-effects of this are that things one would really expect (like using + for angled polygon corners) are not supported. This project subsumes the other, which will eventually become unmaintained. Another advantage to the Go version is that it supports UTF-8 inputs natively. Other features, like tab expansion, have also been introduced.

Some other features, like custom objects, have not yet been implemented.

So... why did you do this?

There are a few reasons:

  • We feel that Markdown is a great format for authoring documents.
  • When authoring technical documents, it's common to want to embed diagrams.
  • People say pictures are worth a thousand words.

Markdown support for inline images isn't particularly great, because you cannot view the image in text mode. An ASCII diagram is usually doable for many illustrations, but is often rendered as text in the HTML output. We'd like the best of both worlds.

Aren't there already things that do this?

Well, yes. There is a project called ditaa that has some of this functionality. When dhobsd initially implemented A2S, ditaa left a couple key points to be desired:

  • Its annotation format was too verbose, distracting from the visual content in text mode.
  • Its output was a rasterized format, so it didn't scale well.

Later, ditaa became unusable. The software it was integrated with was written in PHP, and had to shell out to run ditaa. Because ditaa was written in Java, new JVMs were spawned often to provide real-time feedback on diagram changes. The functionality was re-implemented in PHP to output SVG, but this ultimately ran into the issues described above. Hence this project.

Compilation and Usage

To get the CLI tool, make sure $GOPATH/bin is in your $PATH. Run:

$ go get github.com/asciitosvg/asciitosvg/cmd/a2s
$ a2s -h
 .-------------------------.
 |                         |
 | .---.-. .-----. .-----. |
 | | .-. | +-->  | |  <--| |
 | | '-' | |  <--| +-->  | |
 | '---'-' '-----' '-----' |
 |  ascii     2      svg   |
 |                         |
 '-------------------------'

https://github.com/asciitosvg

[1,0]: {"fill":"#88d","a2s:delref":1}

Usage of go/bin/a2s:
  -L	Generate SVG of the a2s logo.
  -b	Disable drop-shadow blur.
  -f string
        Font family to use. (default "Consolas,Monaco,Anonymous Pro,Anonymous,Bitstream Sans Mono,monospace")
  -i string
        Path to input text file. If set to "-" (hyphen), stdin is used. (default "-")
  -o string
        Path to output SVG file. If set to "-" (hyphen), stdout is used. (default "-")
  -t int
        Tab width. (default 8)
  -x int
        X grid scale in pixels. (default 9)
  -y int
        Y grid scale in pixels. (default 16)

To play with the library:

$ go get github.com/asciitosvg/asciitosvg

Documentation on the API is available through your local godoc server.

Drawing diagrams

Enough yammering about the impetus, code, and functionality. I bet you want to draw something. ASCIIToSVG supports a few different ways to do that.

Basics: polygons and line segments

ASCIIToSVG supports concave and convex polygons with rounded or degree-appropriate corners. Horizontal, vertical, and diagonal lines are all supported. ASCIIToSVG has nearly complete support for output from App::Asciiio. Edges of polygons and line segments can be drawn using the following characters:

  • - or =: Horizontal lines, solid or dashed (respectively).
  • | or :: Vertical lines, solid or dashed (respectively).
  • \ or /: Diagonal lines.
  • +: Edge of a line segment, or an angled corner.

Ticks and dots can be added into the middle of a line segment using x and o, respectively. Note that these characters cannot be inserted into diagonal lines, and they cannot begin a line.

To draw a polygon or turn a line, corners are necessary. The following characters are valid corner characters:

  • ' and .: Quadratic Bézier corners
  • +: Angled corners.

The + token is a control point for lines. It denotes an area where a line intersects another line or traverses a box boundary.

A simple box with 3 rounded corners and a line pointing at it:

+----------.
|          | <---------
'----------'

Diagonals may be used to form a closed polygon, but this is rarely a good idea.

Basics: markers

Markers can be attached at the end of a line to give it a nice arrow by using one of the following characters:

  • <: Left marker
  • >: Right marker
  • ^: Up marker
  • v: Down marker
Basics: text

Text can be inserted at almost any point in the image. Text is rendered in a monospaced font. There aren't many restrictions, but obviously anything you type that looks like it's actually a line or a box is going to be a good candidate for turning into some pretty SVG path. Here is a box with some plain black text in it:

.-------------------------------------.
| Hello here and there and everywhere |
'-------------------------------------'
Basics: formatting

It's possible to change the format of any boxes / polygons you create. This is done (true to markdown form) by providing a reference on the top left edge of the object, and defining that reference at the bottom of the input. References must appear in the input below the objects they are associated with, and preferably at the bottom of the diagram.

An example:

.-------------.  .--------------.
|[Red Box]    |  |[Blue Box]    |
'-------------'  '--------------'

[Red Box]: {"fill":"#aa4444"}
[Blue Box]: {"fill":"#ccccff"}

Text appearing within a stylized box automatically tries to fix the color contrast if the black text would be too dark on the background. The reference commands can take any valid SVG properties / settings for a path element. The commands are specified in JSON form, one per line. Reference commands do not accept nested JSON objects -- don't try to place additional curly braces inside! (Indeed, the current Go implementation currently requires all JSON values other than a2s:delref to be strings.)

By default, the text of a reference is rendered inside the polygon, and the reference is left in-tact in the output. You can remove the reference text using the a2s:delref option; if it is set to any valid JSON value, it will remove the reference text. You can use the a2s:label to replace the text with any value, or to an empty string to remove it entirely.

The a2s:link option will wrap the target object with a clickable link to the URL specified in the value.

Special references

It is possible to reference an object for formatting using its X and Y coordinates. The coordinate system for ASCIIToSVG starts at (0, 0) in the top left of the diagram.

Such references should only be made for stable diagrams, and only if you really need to style text or a line in some particular way. These references are marked by beginning the line with [X,Y] where X is the numeric row and Y is the numeric column of the object's top-left-most point.

Unsupported features

The Go implementation does not yet support all the features of the PHP version. Features that are currently unimplemented include:

  • Custom objects, including the a2s:type format specifier, are not yet implemented.
  • No support is planned for angled corners using #.
  • No support is planned for undirected lines using *.

External Resources

There are some interesting sites that you might be interested in; these are mildly related to the goals of ASCIIToSVG:

  • ditaa (previously mentioned) is a Java utility with a very similar syntax that translates ASCII diagrams into PNG files.
  • App::Asciio (previously mentioned) allows you to programmatically draw ASCII diagrams.
  • Asciiflow is a web front-end to designing ASCII flowcharts.

If you have something really cool that is related to ASCIIToSVG, and I have failed to list it here, do please let me know.

Documentation

Overview

Package asciitosvg provides functionality for parsing ASCII diagrams. It supports diagrams containing UTF-8 content, custom styling of polygons, line segments, and text.

The main interface to the library is through the Canvas. A Canvas is parsed from a byte slice representing the diagram. The byte slice is interpreted as a newline-delimited file, each line representing a row of the diagram. Tabs within the diagram are expanded to spaces based on a specified tab width.

Example usage:

import (
    "fmt"
    "io"

    a2s "github.com/asciitosvg/asciitosvg"
)

...

    c, err := a2s.NewCanvas(diagram, 8)
    if err != nil {
        fmt.Printf("Couldn't create a Canvas: %s\n", err)
    }
    svg := a2s.CanvasToSVG(c, false, "", 16, 9)
    written, err := fd.Write(svg)

...

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CanvasToSVG

func CanvasToSVG(c Canvas, noBlur bool, font string, scaleX, scaleY int) []byte

CanvasToSVG renders the supplied asciitosvg.Canvas to SVG, based on the supplied options.

Types

type Canvas

type Canvas interface {
	// A canvas has an underlying visual representation. The fmt.Stringer interface for this
	// interface provides a view into the underlying grid.
	fmt.Stringer
	// Objects returns all the objects found in the underlying grid.
	Objects() []Object
	// Size returns the visual dimensions of the Canvas.
	Size() image.Point
	// Options returns a map of options to apply to Objects based on the object's tag. This
	// maps tag name to a map of option names to options.
	Options() map[string]map[string]interface{}
	// EnclosingObjects returns the set of objects that contain this point in order from most
	// to least specific.
	EnclosingObjects(p Point) []Object
}

Canvas provides methods for returning objects from an underlying textual grid.

func NewCanvas

func NewCanvas(data []byte, tabWidth int, noBlur bool) (Canvas, error)

NewCanvas returns a new Canvas, initialized from the provided data. If tabWidth is set to a non-negative value, that value will be used to convert tabs to spaces within the grid. Creation of the Canvas can fail if the diagram contains invalid UTF-8 sequences.

type Object

type Object interface {
	fmt.Stringer
	// Points returns all the points occupied by this Object. Every object has at least one point,
	// and all points are both in-order and contiguous.
	Points() []Point
	// HasPoint returns true if the object contains the supplied Point coordinates.
	HasPoint(Point) bool
	// Corners returns all the corners (change of direction) along the path.
	Corners() []Point
	// IsClosed is true if the object is composed of a closed path.
	IsClosed() bool
	// IsDashed is true if this object is a path object, and lines should be drawn dashed.
	IsDashed() bool
	// IsText returns true if the object is textual and does not represent a path.
	IsText() bool
	// Text returns the text associated with this Object if textual, and nil otherwise.
	Text() []rune
	// SetTag sets an options tag on this Object so the renderer may look up options.
	SetTag(string)
	// Tag returns the tag of this object, if any.
	Tag() string
}

Object is an interface for working with open paths (lines), closed paths (polygons), or text.

type Point

type Point struct {
	// The X coordinate of this point.
	X int
	// The Y coordinate of this point.
	Y int
	// Hints for the renderer.
	Hint RenderHint
}

A Point is an X,Y coordinate in the diagram's grid. The grid represents (0, 0) as the top-left of the diagram. The Point also provides hints to the renderer as to how it should be interpreted.

func (Point) String

func (p Point) String() string

String implements fmt.Stringer on Point.

type RenderHint

type RenderHint int

A RenderHint suggests ways the SVG renderer may appropriately represent this point.

const (
	// None indicates no hints are provided for this point.
	None RenderHint = iota
	// RoundedCorner indicates the renderer should smooth corners on this path.
	RoundedCorner
	// StartMarker indicates this point should have an SVG marker-start attribute.
	StartMarker
	// EndMarker indicates this point should have an SVG marker-end attribute.
	EndMarker
	// Tick indicates the renderer should mark a tick in the path at this point.
	Tick
	// Dot indicates the renderer should insert a filled dot in the path at this point.
	Dot
)

Directories

Path Synopsis
cmd
a2s
The a2s tool generates SVG output given an ASCII diagram input.
The a2s tool generates SVG output given an ASCII diagram input.

Jump to

Keyboard shortcuts

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