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

tepra

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2026 License: MIT Imports: 18 Imported by: 0

README

A Go gopher holding a strip of label tape

tepra.tm2

Make label files for KING JIM's TEPRA LINK 2 app.

Test Coverage Go Reference

TEPRA LINK 2 saves labels as .tm2 files. tepra.tm2 writes them. Type a list once, and get one label per line. Then print from the app, as usual.

It works from an AI assistant over MCP, from the command line, and from Go.

[!WARNING] This is an unofficial tool. KING JIM does not document the .tm2 format.

  • tepra.tm2 writes every key that files from the app have.
  • Each setting was checked on the screen of TEPRA LINK 2 for Android, with an SR-MK1.
  • A new release of the app may change the format.

Installation

Tool
Way How
mise (recommended) mise use -g github:mpyw/tepra.tm2
A release binary Download the archive for your OS and CPU from Releases. Put tepra on your PATH. checksums.txt has their SHA-256.
From source go install github.com/mpyw/tepra.tm2/cmd/tepra@latest

Releases cover macOS, Linux and Windows, each on amd64 and arm64.

MCP Server

The MCP server is tepra mcp. First install tepra as a tool, as above. Then add it to your assistant. For Claude Code:

claude mcp add tepra -- tepra mcp
Library
go get github.com/mpyw/tepra.tm2

Usage: As an MCP Server

Ask for labels in your own words. The assistant writes a .tm2 file with the MCP tools. Then print the file from TEPRA LINK 2.

Usage: As a Tool

One label of two lines:

tepra text -o sample.tm2 $'サンプル\nテキスト'
wrote sample.tm2: 1 label, 26.7 mm long, on 18 mm tape

[!TIP] $'...' turns \n into a line break in bash and zsh. A line break inside quotes works too. In PowerShell, write "サンプル`nテキスト".

A label per row of a CSV file, each in the size that fits it:

tepra pages -o pages.tm2 items.csv
wrote pages.tm2: 3 pages, 12.2 to 33.0 mm long, on 18 mm tape

Then print the file from TEPRA LINK 2.

Usage: As a Library

f, err := tepra.NewPages(
	tepra.Tape18mm,
	[]string{"1行目\n2行目", "1行目"},
	tepra.WithAlign(tepra.AlignCenter),
)
if err != nil {
	return err
}
return f.WriteFile("items.tm2")

References

Kinds of label
text pages pour (流し込み)
Labels in a file One One per page One per value
Font size and length Fitted to the label Fitted to each label Same for every label, fitted to the longest
Edit in the app As one label Page by page As pour data, in a table
QR codes and barcodes No No Yes
MCP tool create_text_label create_label_pages create_pour_labels
Command tepra text tepra pages tepra pour
Go NewText NewPages NewPour

[!TIP] For a list of things to label, use pages. Each label gets the size that fits it. Use pour for labels that must look alike, and for codes.

Tapes
Width Go
4, 6, 9, 12, 18, 24, 36 and 50 mm Tape4mm to Tape50mm, or LookupTape(width)

The sizes of each tape come from a file the app wrote on it.

Layout

Size and length:

  • Text fills the height of the tape, unless a font size is given.
  • A label is as long as what is on it, and at least 12 mm with its margins. The app makes no shorter label.
  • A label of a fixed length has its content centred. Text too long for it gets smaller, unless a font size is given.
  • All the labels of a pour file have one font size, the one that fits the value of most lines.

What you see when you edit the label in the app:

  • A border is an empty box of its own, around the text.
  • Inverted text of more than one line is a box per line. In a pour file, each line is a column of its own: Label, Label 2 and on.

[!NOTE] On 4 mm tape, a border's padding of 1.5 mm leaves no room for text. Give a padding of 0.3 mm there.

Print the file
  1. Send the .tm2 file to your phone, such as through Google Drive.
  2. Open it with TEPRA LINK 2, through the share menu of the OS.
  3. Check the labels in the app, and print.
MCP tools

tepra mcp serves these on stdin and stdout:

Tool Kind What it does
create_text_label text Writes a file of one label
create_label_pages pages Writes a file of one page per string
create_pour_labels pour Writes a pour file: one label per string
inspect_label Describes a .tm2 file

Inputs:

  • The tools that write a file take the tool options, in snake case.
  • A length in mm ends in _mm, and a picture in _path. Examples: font_size, rotate, padding_mm, icon_path.
  • code and column are for create_pour_labels only.
  • Paths must be absolute, for the file and for pictures.
  • A file is not replaced unless overwrite is true.
  • A line break in a label is \n.
Commands
Command What it does
tepra text [options] text Writes one label. A line break in the text breaks it into lines
tepra pages [options] [file.csv] Writes a page per row of the file
tepra pour [options] [file.csv] Writes a pour label per row of the file
tepra inspect file.tm2 Shows what a .tm2 file holds
tepra mcp Serves the MCP tools on stdin and stdout

A pour file of the same items.csv:

tepra pour -o items.tm2 items.csv
wrote items.tm2: 3 labels, 12.2 mm each, on 18 mm tape

A QR code per URL, one label each:

tepra pour --code qr -o qr.tm2 urls.csv
wrote qr.tm2: 2 labels, 17.2 mm each, on 18 mm tape

A label of a fixed length, with a rounded border:

tepra text --length 60 --border rounded --align center -o fixed.tm2 サンプル
wrote fixed.tm2: 1 label, 60.0 mm long, on 18 mm tape

Text turned 90 degrees, and text in white on black:

tepra text --rotate 90 -o turned.tm2 $'サンプル\nテキスト'
tepra text --fill inverted --bold -o inverted.tm2 サンプル
wrote turned.tm2: 1 label, 12.0 mm long, on 18 mm tape
wrote inverted.tm2: 1 label, 51.4 mm long, on 18 mm tape
The CSV file

pages and pour read a CSV file of one column. Without a file, or with -, they read stdin.

  • Each row is a label.
  • A line break in a value breaks the label into lines.
  • A value in double quotes may hold line breaks and commas.
  • Blank rows are skipped. So are spaces around a value.
  • A row of two or more columns is an error.

This items.csv makes three labels:

"1行目
2行目
3行目"
"1行目
2行目"
1行目

[!TIP] A file with one value per line is a CSV file of one column already. Quote only the values that hold a line break or a comma. Spreadsheets quote such values when they save a CSV file.

Tool options

text, pages and pour all take these. In pages and pour they apply to every label.

Option Default Meaning
-o, --output (required) The .tm2 file to write. Its name, without .tm2, names the label in the app
-f, --force off Replace the file when it exists
--tape 18 Tape width in mm: 4, 6, 9, 12, 18, 24, 36 or 50
--font-size fit Font size in points. By default the text fills the tape
--bold off Bold text
--align left Where each line goes across: left, center or right
--valign middle Where the text goes down: top, middle or bottom
--rotate 0 Turn the text clockwise: 0, 90, 180 or 270 degrees
--vertical off Write the text top to bottom
--fill none The box behind the text: none, inverted (white on black) or shaded (a light dotted box)
--border none The line around the label: none, box, rounded, top-bottom, top or bottom
--border-width 0.7 The width of the border. 0.35 is thin, 2.8 is thick
--icon none A PNG, JPEG or GIF file to put before the text, as high as the tape prints
--background none A PNG, JPEG or GIF file to stretch under the whole label, such as a frame
--image-mode threshold How pictures turn black and white: threshold, diffusion or screen
--image-threshold 128 The grey level, 0 to 255, below which a pixel is black
--padding 0 Blank between the label's edges and its text, in mm. 1.5 with a border
--margin 1 Blank tape before and after the label, in mm, 1 to 500
--length fit Make the label this long, margins included, in mm, 10 to 3000

Only pour takes these:

Option Default Meaning
--code text Show each value as a code: text, qr, code39, code128 or jan13
--column Label Title of the pour column in the app

[!NOTE] --code jan13 takes 12 digits. The app adds the check digit.

tepra inspect

tepra inspect shows what a .tm2 file holds. It reads files the app wrote, too.

$ tepra inspect items.tm2
file:    items.tm2 (version 2.0.0, saved 2026/10/18 06:12)
tape:    18 mm, pour, label 12.2 mm long, margin 1.0 mm
drawers:
  pour   x   0.0  y   1.6  w  10.2  h  15.2 mm  column 0, size 11.5, OTBGoStdR-Normal
rows:    3, column "Label"
    1  1行目 / 2行目 / 3行目
    2  1行目 / 2行目
    3  1行目

A file of pages shows each page. Pages count from 1, as in the app:

$ tepra inspect pages.tm2
file:    pages.tm2 (version 2.0.0, saved 2026/10/18 06:12)
page 1:
tape:    18 mm, plain, label 12.2 mm long, margin 1.0 mm
drawers:
  text   x   0.0  y   1.6  w  10.2  h  15.2 mm  size 11.5, OTBGoStdR-Normal, "1行目\n2行目\n3行目"
page 2:
tape:    18 mm, plain, label 17.5 mm long, margin 1.0 mm
drawers:
  text   x   0.0  y   1.6  w  15.5  h  15.2 mm  size 17.5, OTBGoStdR-Normal, "1行目\n2行目"
page 3:
tape:    18 mm, plain, label 33.0 mm long, margin 1.0 mm
drawers:
  text   x   0.0  y   1.6  w  31.0  h  15.2 mm  size 35, OTBGoStdR-Normal, "1行目"
Functions
Function Returns
NewText(tape, text, opts...) A file of one label
NewPages(tape, texts, opts...) A file of a page per string, each fitted
NewPour(tape, column, values, opts...) A pour file of a label per string, under the column's title
ReadFile(path), ParseFile(r) A file read back

A File writes itself with WriteFile or WriteTo.

Library options

Each With function sets one thing. What no option sets is as the app sets it.

Option Default Meaning
WithName(name) "label" Names the label in the app, without .tm2
WithTime(t) now The file's date
WithFontSize(pt) fit Font size in points. By default the text fills the tape
WithBold() off Bold text
WithAlign(a) AlignLeft Where each line goes across: AlignLeft, AlignCenter or AlignRight
WithVerticalAlign(a) VerticalAlignMiddle Where the text goes down: VerticalAlignTop, VerticalAlignMiddle or VerticalAlignBottom
WithRotation(r) RotationNone Turn the text clockwise: RotationNone, Rotation90, Rotation180 or Rotation270
WithVertical() off Write the text top to bottom
WithFill(m) FillNone The box behind the text: FillNone, FillInverted or FillShaded
WithBorder(b) BorderNone The line around the label: BorderNone, BorderBox, BorderRounded, BorderTopBottom, BorderTop or BorderBottom
WithBorderWidth(w) 0.7 The width of the border
WithIcon(picture) none PNG, JPEG or GIF bytes to put before the text
WithBackground(picture) none PNG, JPEG or GIF bytes to stretch under the whole label
WithImageMode(m) ImageModeThreshold How pictures turn black and white: ImageModeThreshold, ImageModeDiffusion or ImageModeScreen
WithImageThreshold(level) 128 The grey level, 0 to 255, below which a pixel is black
WithPaddingMM(mm) 0 Blank between the label's edges and its text. 1.5 with a border
WithMarginMM(mm) 1 Blank tape before and after the label, 1 to 500
WithLengthMM(mm) fit Make the label this long, margins included, 10 to 3000
WithCode(k) CodeText Pour only. Show each value as a code: CodeText, CodeQR, CodeCODE39, CodeCODE128 or CodeJAN13
Option types

The type of an option says which functions take it:

Type Returned by Taken by
Option Every With function but WithCode NewText, NewPages and NewPour
PourOnlyOption WithCode NewPour
f, err := tepra.NewPour(
	tepra.Tape18mm,
	"URL",
	[]string{"https://example.com/"},
	tepra.WithCode(tepra.CodeQR),
)
Errors

Every error wraps one of these. Test it with errors.Is.

Error When
ErrInvalidOptions An option out of range, such as a margin under 1 mm
ErrCrashesApp A value the app crashes on, such as alignment 3. It is never written
ErrTapeNotSupported A tape width whose sizes are not known
ErrUnknownName A name ParseRotation, ParseCodeKind and the like do not know
ErrNoText No text, or no values or pages
ErrOverLimit More rows, characters or columns than the app takes
ErrNoRoom Padding or a fixed length that leaves no room
ErrBadImage A picture that is not PNG, JPEG or GIF
ErrBadCode A value the kind of code cannot hold, such as 13 digits for JAN-13
Reading files
  • ReadFile and ParseFile read a .tm2 file, from the app or from this package.
  • Drawer types the package does not know are kept as RawDrawer.
  • Writing the file back keeps them as they were.

License

tepra.tm2 is under the MIT License.

The mascot is a Go gopher holding a strip of label tape. The Go gopher was designed by Renée French, under CC BY 4.0.

Documentation

Overview

Package tepra reads and writes .tm2 files, the labels of TEPRA LINK 2.

TEPRA LINK 2 is KING JIM's app for the "TEPRA" PRO label printers. A .tm2 file is one line of JSON. This package builds such files, so a label can be made elsewhere, opened in the app and printed from there. It does not talk to a printer.

The format is not documented. This package follows files the app wrote, and writes every key they have. The keys of an object come in the order of the fields of its type, not of those files.

Lengths are in points (1/72 inch), as in the file, unless a name says mm.

Index

Constants

View Source
const (
	DrawerTypeText  = "text"
	DrawerTypePour  = "pour"
	DrawerTypeImage = "image"
)

The drawer types this package knows.

View Source
const (
	PourMaxRows      = 1000
	PourMaxCellRunes = 1000
)

The limits of the app's pour data.

View Source
const (
	FontGothic     = "OTBGoStdR-Normal"
	FontGothicBold = "OTBGoStdB-Normal"
)

The fonts of TEPRA LINK 2, by the names the app writes.

View Source
const DefaultBorderPaddingMM = 1.5

DefaultBorderPaddingMM is the padding of a label with a border and no WithPaddingMM, in mm.

View Source
const DefaultBorderWidth = 0.7

DefaultBorderWidth is the width of a border as the app writes it. In the app, 0.35 showed thinner, and 1.4 and 2.8 wider.

View Source
const DefaultImageThreshold = 128

DefaultImageThreshold is the threshold of a picture of a template of the app.

View Source
const DefaultMarginMM = 1.0

DefaultMarginMM is the blank tape before and after a label as the app sets it, in mm.

View Source
const FileTableColumns = 50

FileTableColumns is how many columns the app writes in the table, used or not.

View Source
const FileVersion = "2.0.0"

FileVersion is the "version" TEPRA LINK 2 writes.

Variables

View Source
var (
	// ErrTapeNotSupported is a tape width whose sizes are not known.
	ErrTapeNotSupported = errors.New("tepra: tape width not supported")
	// ErrUnknownName is a name ParseFillMode, ParseBorderType, ParseAlign or
	// ParseVerticalAlign does not know.
	ErrUnknownName = errors.New("tepra: unknown name")
	// ErrInvalidOptions is an Option, or options together, that NewPour or
	// NewText cannot use.
	ErrInvalidOptions = errors.New("tepra: invalid options")
	// ErrCrashesApp is a value TEPRA LINK 2 crashes on. It is not written.
	ErrCrashesApp = errors.New("tepra: the app crashes on it")
	// ErrNoText is a label with no text: an empty text, or no values to
	// pour.
	ErrNoText = errors.New("tepra: no text")
	// ErrOverLimit is more than the app takes: rows, characters in a cell,
	// or columns.
	ErrOverLimit = errors.New("tepra: over the app's limit")
	// ErrNoRoom is padding that leaves no room on the tape.
	ErrNoRoom = errors.New("tepra: no room on the tape")
	// ErrBadImage is a picture that cannot be read as PNG, JPEG or GIF.
	ErrBadImage = errors.New("tepra: bad picture")
	// ErrBadCode is a value that cannot be shown as the kind of code asked
	// for.
	ErrBadCode = errors.New("tepra: bad value for a code")
)

The errors of this package. Each error it returns wraps one or more of these, to test with errors.Is.

View Source
var (
	Tape4mm  = Tape{WidthMM: 4, PrintableHeight: 8.8, FrameHeight: 12}
	Tape6mm  = Tape{WidthMM: 6, PrintableHeight: 14.400001, FrameHeight: 18}
	Tape9mm  = Tape{WidthMM: 9, PrintableHeight: 21.6, FrameHeight: 26}
	Tape12mm = Tape{WidthMM: 12, PrintableHeight: 28.800001, FrameHeight: 35}
	Tape18mm = Tape{WidthMM: 18, PrintableHeight: 43.2, FrameHeight: 52}
	Tape24mm = Tape{WidthMM: 24, PrintableHeight: 51.2, FrameHeight: 69}
	Tape36mm = Tape{WidthMM: 36, PrintableHeight: 76.8, FrameHeight: 103}
	Tape50mm = Tape{WidthMM: 50, PrintableHeight: 135.8, FrameHeight: 142}
)

The tapes whose sizes are known. Each one's sizes come from a file the app wrote for it, in testdata.

View Source
var (
	Black = Color{0, 0, 0, 1}
	White = Color{1, 1, 1, 1}
)

The colors the app writes for black text on a white tape.

Tapes are the tapes whose sizes are known, narrowest first. Other widths need a file the app wrote for them.

Functions

func MMToPoints

func MMToPoints(mm float64) float64

MMToPoints converts a length in mm to points.

func PointsToMM

func PointsToMM(pt float64) float64

PointsToMM converts a length in points to mm.

Types

type Align

type Align int

Align is where a text box puts each line across its frame. Each value was seen in TEPRA LINK 2 for Android, opening a file this package wrote. The app crashes on a file with 3.

const (
	AlignLeft   Align = 0
	AlignCenter Align = 1
	AlignRight  Align = 2
)

The alignments across.

func ParseAlign

func ParseAlign(name string) (Align, error)

ParseAlign returns the alignment of a name: left, center or right.

func (Align) String

func (a Align) String() string

String returns the name of a, as ParseAlign takes it.

func (Align) Valid

func (a Align) Valid() bool

Valid reports whether a is one of the alignments the app opens.

type BaseDrawer

type BaseDrawer struct {
	// Identifier is a UUID, unique in the file.
	Identifier string `json:"-"`

	// Rotate turns the drawer in Frame.
	Rotate Rotation `json:"Rotate"`
	// TapeForegroundColor is the color the app shows the text in, Black as
	// it writes it. White showed white text on the white tape.
	TapeForegroundColor Color `json:"tapeForegroundColor"`
	// Frame is where the drawer is in the document's frame. A text box fits
	// its text to it unless SizePriority is set. A picture fits in it,
	// keeping its shape, centred.
	Frame Rect `json:"frame"`
	// BIType is the line drawn on the edges of Frame.
	BIType BorderType `json:"BIType"`
	// BILineWidthValue is the width of the BIType line, DefaultBorderWidth
	// as the app writes it. It is spelled "BILineWidhValue" in the file.
	BILineWidthValue float64 `json:"BILineWidhValue"`

	// Below: written as the app writes them. Values tried showed no change
	// in the app, or none were tried.
	// TapeBackgroundColor: Black did not fill the box behind the text.
	TapeBackgroundColor Color `json:"tapeBackgroundColor"`
	// BILineThickness, BILineStyle and BILineWidth: thickness 1 to 3, style
	// 0 to 4 and width 0.5 to 2, with box and rounded borders.
	BILineThickness int     `json:"BILineThickness"`
	BILineStyle     int     `json:"BILineStyle"`
	BILineWidth     float64 `json:"BILineWidth"`
	// TapeVertical, TapeTapeFrame and FrameTop: set, and a frame of
	// [0, 0, 40, 20].
	TapeVertical  bool `json:"tapeVertical"`
	TapeTapeFrame Rect `json:"tapeTapeFrame"`
	FrameTop      bool `json:"frameTop"`
}

BaseDrawer holds the fields every drawer has.

func (*BaseDrawer) Base

func (b *BaseDrawer) Base() *BaseDrawer

Base returns b.

type BorderType

type BorderType int

BorderType is the line a drawer draws around its frame. Each type was seen in the app, opening a file this package wrote. Values from 6 up drew no line.

const (
	BorderNone      BorderType = 0
	BorderBox       BorderType = 1
	BorderRounded   BorderType = 2
	BorderTopBottom BorderType = 3
	BorderTop       BorderType = 4
	BorderBottom    BorderType = 5
)

The border types.

func ParseBorderType

func ParseBorderType(name string) (BorderType, error)

ParseBorderType returns the border type of a name: none, box, rounded, top-bottom, top or bottom.

func (BorderType) String

func (b BorderType) String() string

String returns the name of b, as ParseBorderType takes it.

func (BorderType) Valid

func (b BorderType) Valid() bool

Valid reports whether b is one of the border types known to draw.

type CodeKind

type CodeKind int

CodeKind is what a PourDrawer shows its column as: text, or a code made of it. 1 showed a QR code in the app, and 2 and 3 barcodes. That 2 and 3 are CODE39 and CODE128, and 4 JAN-13, follows the order of the app's manual.

const (
	CodeText    CodeKind = 0
	CodeQR      CodeKind = 1
	CodeCODE39  CodeKind = 2
	CodeCODE128 CodeKind = 3
	// CodeJAN13 takes 12 digits. The app adds the check digit.
	CodeJAN13 CodeKind = 4
)

The kinds of code.

func ParseCodeKind

func ParseCodeKind(name string) (CodeKind, error)

ParseCodeKind returns the kind of code of a name: text, qr, code39, code128 or jan13.

func (CodeKind) String

func (k CodeKind) String() string

String returns the name of k, as ParseCodeKind takes it.

func (CodeKind) Valid

func (k CodeKind) Valid() bool

Valid reports whether k is one of the kinds of code known.

type Color

type Color [4]float64

Color is red, green, blue and alpha, each from 0 to 1.

type Document

type Document struct {
	// Drawers are drawn in order, each over the ones before.
	Drawers Drawers `json:"drawers"`
	// Frame is the label without its margins. Its width is the label's
	// length, as the app showed it.
	Frame Rect `json:"frame"`
	// TapeWidthMM is the tape's width in mm. The app shows the label on a
	// tape of this width.
	TapeWidthMM int `json:"SettingsTapeWidth"`
	// PrintableArea is the height of the band the app prints on, in points.
	// It is the tape's PrintableHeight. A smaller value showed a smaller
	// band.
	PrintableArea float64 `json:"SettingsPrintableArea"`
	// AutoLength makes the label as long as Frame. Unset, the label is
	// FixedLength long.
	AutoLength  bool    `json:"SettingsAutoLength"`
	FixedLength float64 `json:"SettingsFixedLength"`
	// Margin is the blank tape before and after Frame, in points.
	Margin float64 `json:"SettingsMargin"`
	// ForegroundColor and BackgroundColor are the colors of the tape's ink
	// and of the tape, as the app shows the label. Swapped, the whole label
	// showed black.
	ForegroundColor Color `json:"SettingsForegroundColor"`
	BackgroundColor Color `json:"SettingsBackgroundColor"`
	// TapeVertical turns the whole label to run down the tape.
	TapeVertical bool `json:"SettingsTapeVertical"`
	// MultiplePage shows the app's controls for more than one page. The app
	// sets it on a pour label.
	MultiplePage bool `json:"MultiplePage"`
	// PourMode shows the label in the app's pour form (流し込み), filled
	// from the file's TableData. Unset, it is a plain label (一般).
	PourMode bool `json:"PourMode"`

	// Below: written as the app writes them. Values tried showed no change
	// in the app, or none were tried.
	// Name and PrintableFrame: another name, and half the width.
	Name                string `json:"name"`
	PrintableFrame      Rect   `json:"printableFrame"`
	Identifier          string `json:"identifier"`
	ForegroundColorName string `json:"SettingsForegroundColorName"`
	BackgroundColorName string `json:"SettingsBackgroundColorName"`
}

Document is one label of a file: the tape settings and its drawers.

func (*Document) LengthMM

func (d *Document) LengthMM() float64

LengthMM is the length of tape the label takes, margins included, in mm.

type Drawer

type Drawer interface {
	// DrawerType is the drawer's "type" in the file.
	DrawerType() string
	// Base returns the fields every drawer has.
	Base() *BaseDrawer
}

Drawer is an object on a label: a TextDrawer, PourDrawer, ImageDrawer, or a RawDrawer for a type this package does not know.

type Drawers

type Drawers []Drawer

Drawers are the objects of a Document, drawn in order.

func (Drawers) MarshalJSON

func (ds Drawers) MarshalJSON() ([]byte, error)

MarshalJSON is MarshalJSONTo, for encoding/json version 1. encoding/json escapes <, > and & in what it returns, which the app does not.

func (Drawers) MarshalJSONTo

func (ds Drawers) MarshalJSONTo(enc *jsontext.Encoder) error

MarshalJSONTo writes each drawer as the app does: "type", "identifier" and an empty key come first, then the drawer's fields.

func (*Drawers) UnmarshalJSON

func (ds *Drawers) UnmarshalJSON(data []byte) error

UnmarshalJSON is UnmarshalJSONFrom, for encoding/json version 1.

func (*Drawers) UnmarshalJSONFrom

func (ds *Drawers) UnmarshalJSONFrom(dec *jsontext.Decoder) error

UnmarshalJSONFrom reads drawers by their "type". An unknown type becomes a RawDrawer.

type File

type File struct {
	// Documents are the pages of the file, a label each. The app lists them
	// when the first has MultiplePage set, and prints them together.
	Documents []Document `json:"documents"`
	// CurrentPage is the document the app opens, from 0. The app crashes on
	// a file whose CurrentPage has no document.
	CurrentPage int `json:"currentPage"`
	// FileName is the name the app shows the label by, with ".tm2". It is
	// not the name of the file the app opened.
	FileName string `json:"fileName"`
	// TableData is the data a PourDrawer fills from: one row, and one label,
	// per value, of FileTableColumns cells each.
	TableData [][]string `json:"tableData"`
	// TableHeader is the title of each column of TableData, shown in the
	// app's pour data editor.
	TableHeader []string `json:"tableHeader"`

	// Below: written as the app writes them. Values tried showed no change
	// in the app, or none were tried.
	// SavedLength and Version: 999 or left out, and "1.0.0". Date,
	// TextWords, Category, Keywords and the catalog titles do not show where
	// the app edits a label.
	SavedLength    *float64 `json:"savedLength,omitzero"`
	Version        string   `json:"version"`
	Date           string   `json:"date"`
	TextWords      string   `json:"textWords"`
	Category       string   `json:"category"`
	Keywords       string   `json:"keywords"`
	CatalogTitle   string   `json:"CatalogTitle"`
	CatalogTitleEN string   `json:"CatalogTitleEN"`
	KeywordsEN     string   `json:"keywordsEN"`
}

File is a .tm2 file.

func NewPages

func NewPages(tape Tape, texts []string, opts ...TextOption) (*File, error)

NewPages returns a file of one page per text, each laid out as NewText lays out its label. So each label has a font size and a length of its own, unlike the labels of NewPour. The app lists the pages, and prints them together. A text may hold line breaks ("\n").

func NewPour

func NewPour(tape Tape, column string, values []string, opts ...PourOption) (*File, error)

NewPour returns a file that prints one label per value, with the column titled column. A value may hold line breaks ("\n"). All the labels share one frame, sized for the longest value.

Inverted text of more than one line is poured from a column per line: column, then column 2, column 3 and on.

The text keeps its font size on every label. The app would otherwise fit each value to the shared frame: a value of fewer lines would grow to its height, and run past its sides.

func NewText

func NewText(tape Tape, text string, opts ...TextOption) (*File, error)

NewText returns a file of one label that prints text. text may hold line breaks ("\n").

func ParseFile

func ParseFile(r io.Reader) (*File, error)

ParseFile reads a .tm2 file from r.

func ReadFile

func ReadFile(path string) (*File, error)

ReadFile reads the .tm2 file at path.

func (*File) MarshalJSON

func (f *File) MarshalJSON() ([]byte, error)

MarshalJSON is MarshalJSONTo, for encoding/json version 1. encoding/json escapes <, > and & in what it returns, which the app does not.

func (*File) MarshalJSONTo

func (f *File) MarshalJSONTo(enc *jsontext.Encoder) error

MarshalJSONTo writes f, unless the app would crash on it.

func (*File) WriteFile

func (f *File) WriteFile(path string) error

WriteFile writes f to path, replacing a file there.

func (*File) WriteTo

func (f *File) WriteTo(w io.Writer) (int64, error)

WriteTo writes f to w as a .tm2 file: one line of JSON, with <, > and & as they are, as the app writes them.

type FillMode

type FillMode int

FillMode is how a text box fills the box behind its text. Each mode was seen in TEPRA LINK 2 for Android, opening a file this package wrote. The app crashes on a file with any other value, from 3 up.

const (
	// FillNone is black text on the tape.
	FillNone FillMode = 0
	// FillInverted is white text on a black box the size of the frame. The
	// app shows only the last line of such a box, so NewPour and NewText
	// give each line a box of its own.
	FillInverted FillMode = 1
	// FillShaded is black text on a light, dotted box the size of the frame.
	FillShaded FillMode = 2
)

The fill modes.

func ParseFillMode

func ParseFillMode(name string) (FillMode, error)

ParseFillMode returns the fill mode of a name: none, inverted or shaded.

func (FillMode) String

func (m FillMode) String() string

String returns the name of m, as ParseFillMode takes it.

func (FillMode) Valid

func (m FillMode) Valid() bool

Valid reports whether m is one of the fill modes the app opens.

type ImageDrawer

type ImageDrawer struct {
	BaseDrawer

	// Image is a PNG, base64 in the file. The app fits it in Frame, keeping
	// its shape, centred.
	Image []byte `json:"image"`
	// ImageKind is 3 as the app writes it. 1 showed the picture in grey,
	// not turned to black and white. 0 and 2 showed no change.
	ImageKind int `json:"imageKind"`
	// ImageMode is how the picture turns to black and white.
	ImageMode ImageMode `json:"imageMode"`
	// ImageThreshold is the grey level, from 0 to 255, below which a pixel
	// is black, with ImageModeThreshold.
	ImageThreshold int `json:"imageThreshold"`

	// Below: written as the app writes them. Values tried showed no change
	// in the app, or none were tried.
	// ImageBlock and ImageOffset: 50, and 0.
	ImageBlock  int `json:"imageBlock"`
	ImageOffset int `json:"imageOffset"`
}

ImageDrawer is a picture.

func NewImageDrawer

func NewImageDrawer(png []byte, frame Rect) *ImageDrawer

NewImageDrawer returns a picture in frame, set as in a file the app wrote. The app fits png in frame, keeping its shape, centred. It turns it to black and white at ImageThreshold.

func (*ImageDrawer) DrawerType

func (*ImageDrawer) DrawerType() string

DrawerType returns DrawerTypeImage.

type ImageMode

type ImageMode int

ImageMode is how the app turns a picture to black and white. Each mode was seen in the app, opening a file this package wrote. 0 and 4 showed as ImageModeThreshold does.

const (
	// ImageModeDiffusion spreads the error of each pixel to the next ones:
	// grey shows as scattered dots.
	ImageModeDiffusion ImageMode = 1
	// ImageModeThreshold makes each pixel black below ImageThreshold. It is
	// the mode of a picture of a template of the app.
	ImageModeThreshold ImageMode = 2
	// ImageModeScreen shows grey as a regular screen of dots.
	ImageModeScreen ImageMode = 3
)

The modes the app showed differently.

func ParseImageMode

func ParseImageMode(name string) (ImageMode, error)

ParseImageMode returns the mode of a name: diffusion, threshold or screen.

func (ImageMode) String

func (m ImageMode) String() string

String returns the name of m, as ParseImageMode takes it.

func (ImageMode) Valid

func (m ImageMode) Valid() bool

Valid reports whether m is one of the modes known.

type Option

type Option func(*optionConfig)

Option sets something every kind of label has. NewText, NewPages and NewPour all take it: it is a TextOption and a PourOption. Each With function returns one, but WithCode. What no option sets is as the app sets it.

func WithAlign

func WithAlign(a Align) Option

WithAlign sets where each line of text goes across its frame. It is AlignLeft by default, as the app sets it.

func WithBackground

func WithBackground(picture []byte) Option

WithBackground stretches a PNG, JPEG or GIF picture under the whole label.

func WithBold

func WithBold() Option

WithBold writes the text in FontGothicBold.

func WithBorder

func WithBorder(b BorderType) Option

WithBorder draws a line around the label, on a box of its own. The text keeps DefaultBorderPaddingMM from it, unless WithPaddingMM is given.

func WithBorderWidth

func WithBorderWidth(w float64) Option

WithBorderWidth sets the width of the border. It is DefaultBorderWidth by default.

func WithFill

func WithFill(m FillMode) Option

WithFill sets the box behind the text.

func WithFontSize

func WithFontSize(pt float64) Option

WithFontSize sets the size of the text, in points. By default it is the size at which the text fills the tape.

func WithIcon

func WithIcon(picture []byte) Option

WithIcon puts a PNG, JPEG or GIF picture before the text, as high as the tape prints, keeping its shape.

func WithImageMode

func WithImageMode(m ImageMode) Option

WithImageMode sets how the app turns the icon and the background to black and white. It is ImageModeThreshold by default.

func WithImageThreshold

func WithImageThreshold(level int) Option

WithImageThreshold sets the grey level, from 0 to 255, below which a pixel of the icon and the background is black, with ImageModeThreshold. It is DefaultImageThreshold by default.

func WithLengthMM

func WithLengthMM(mm float64) Option

WithLengthMM makes the label this long, margins included, in mm, from 10 to 3000 as the app takes it. By default the label is as long as what is on it. Text that does not fit gets smaller, unless WithFontSize is given, and what is on the label is centred.

func WithMarginMM

func WithMarginMM(mm float64) Option

WithMarginMM sets the blank tape before and after the label, in mm, from 1 to 500 as the app takes it. It is DefaultMarginMM by default.

func WithName

func WithName(name string) Option

WithName names the file in the app, without ".tm2". It is "label" by default.

func WithPaddingMM

func WithPaddingMM(mm float64) Option

WithPaddingMM sets the blank between the label's edges and what is on it, in mm: room for a border, or for the frame of a background.

func WithRotation

func WithRotation(r Rotation) Option

WithRotation turns the text. Rotation90 and Rotation270 run its lines across the tape.

func WithTime

func WithTime(t time.Time) Option

WithTime sets the file's date. It is the time of NewPour or NewText by default.

func WithVertical

func WithVertical() Option

WithVertical writes the text top to bottom, each line to the left of the one before. Its lines run across the tape, as with Rotation90.

func WithVerticalAlign

func WithVerticalAlign(a VerticalAlign) Option

WithVerticalAlign sets where the text goes down its frame. It is VerticalAlignMiddle by default, as the app sets it.

type PourDrawer

type PourDrawer struct {
	TextDrawer

	// ColumnNumber is the column of the file's TableData the box shows, from
	// 0.
	ColumnNumber int `json:"ColumnNumber"`
	// Attribute is what the column shows as: text, or a code made of it.
	Attribute CodeKind `json:"Attribute"`
}

PourDrawer is a text box filled from a column of the file's table, one label per row.

func NewPourDrawer

func NewPourDrawer(column int, text string, frame Rect) *PourDrawer

NewPourDrawer returns a text box in frame for column, showing text in the editor.

func (*PourDrawer) DrawerType

func (*PourDrawer) DrawerType() string

DrawerType returns DrawerTypePour.

type PourOnlyOption

type PourOnlyOption func(*optionConfig)

PourOnlyOption sets what only the labels of NewPour have. It is not a TextOption, so NewText and NewPages do not compile with it.

func WithCode

func WithCode(k CodeKind) PourOnlyOption

WithCode shows each value of NewPour as a code instead of text. The app shows codes in pour data only, so NewText and NewPages do not take it.

type PourOption

type PourOption interface {
	// contains filtered or unexported methods
}

PourOption sets something of the labels NewPour makes. An Option is one, and so is a PourOnlyOption.

type RawDrawer

type RawDrawer struct {
	// BaseDrawer holds the fields every drawer has, as read. Changing them
	// does not change what is written.
	BaseDrawer

	// Type is the drawer's "type".
	Type string
	// JSON is the drawer as read.
	JSON jsontext.Value
}

RawDrawer is a drawer of a type this package does not know. It is written back as it was read.

func (*RawDrawer) DrawerType

func (r *RawDrawer) DrawerType() string

DrawerType returns r.Type.

type Rect

type Rect [4]float64

Rect is a frame: x, y, width and height, in points. y grows down the tape.

type Rotation

type Rotation int

Rotation turns a drawer in its frame, by a quarter turn or a half turn. Each value was seen in TEPRA LINK 2 for Android, opening a file this package wrote. The app crashes on a file with 90, and so on any value it does not know.

const (
	RotationNone Rotation = 0
	Rotation180  Rotation = 1
	// Rotation270 turns the text a quarter turn left: it reads bottom to
	// top.
	Rotation270 Rotation = 2
	// Rotation90 turns the text a quarter turn right: it reads top to
	// bottom.
	Rotation90 Rotation = 3
)

The rotations, clockwise.

func ParseRotation

func ParseRotation(name string) (Rotation, error)

ParseRotation returns the rotation of a name, in degrees clockwise: 0, 90, 180 or 270.

func (Rotation) String

func (r Rotation) String() string

String returns the name of r, as ParseRotation takes it.

func (Rotation) Valid

func (r Rotation) Valid() bool

Valid reports whether r is one of the rotations the app opens.

type Tape

type Tape struct {
	// WidthMM is the tape's width in mm, as in SettingsTapeWidth.
	WidthMM int
	// PrintableHeight is the height the printer can print on, in points.
	PrintableHeight float64
	// FrameHeight is the height of the label's frame, in points. The
	// printable band sits in its middle.
	FrameHeight float64
}

Tape is a tape width and the sizes the app writes for it.

func LookupTape

func LookupTape(widthMM int) (Tape, error)

LookupTape returns the tape of a width in mm.

func (Tape) PrintableTop

func (t Tape) PrintableTop() float64

PrintableTop is the y of the printable band in the frame, in points.

type TextDrawer

type TextDrawer struct {
	BaseDrawer

	// Text is what the box shows. "\n" breaks a line.
	Text string `json:"TIText"`
	// FontName is FontGothic or FontGothicBold. Other fonts were not tried.
	FontName string `json:"TIFontName"`
	// FontSize is the size of the text, in points. The app uses it only with
	// SizePriority. Otherwise it fits the text to Frame.
	FontSize float64 `json:"TIFontSize"`
	// Alignment is where each line goes across Frame.
	Alignment Align `json:"TIAlignment"`
	// VerticalAlignment is where the lines go down Frame.
	VerticalAlignment VerticalAlign `json:"TIVerticalAlignment"`
	// FillMode is the box behind the text.
	FillMode FillMode `json:"TIFillMode"`
	// FontFace is 1 as the app writes it. 0 showed no change. The app
	// crashes on 2, so other values are not written.
	FontFace int `json:"TIFontFace"`
	// TextVertical writes the lines top to bottom, each to the left of the
	// one before.
	TextVertical bool `json:"textVertical"`
	// HasPlaceholder shows "未入力のテキストボックス" in grey instead of
	// Text. The app sets it on a box with no text.
	HasPlaceholder bool `json:"hasPlaceholder"`
	// HoldAspect, set as the app sets it, fits the text to Frame, unless
	// SizePriority is set. Unset, the text keeps FontSize, its lines close
	// up, and the app marks the box 固.
	HoldAspect bool `json:"holdAspect"`
	// SizePriority keeps FontSize instead of fitting the text to Frame.
	SizePriority bool `json:"sizePriority"`

	// Below: written as the app writes them. Values tried showed no change
	// in the app, or none were tried.
	// Color: grey, red and white. TapeForegroundColor is the color shown.
	Color Color `json:"TIColor"`
	// Bold and Italic: set. FontGothicBold is how the app writes bold.
	Bold   bool `json:"TIBold"`
	Italic bool `json:"TIItalic"`
	// LineBreak: 0, 1 and 3, on text of two lines broken by "\n".
	LineBreak int `json:"TILineBreak"`
	// TextMargin: up to [3, 3], fitted to Frame and with SizePriority.
	TextMargin [2]float64 `json:"textMargin"`
}

TextDrawer is a text box.

func NewTextDrawer

func NewTextDrawer(text string, frame Rect) *TextDrawer

NewTextDrawer returns a text box in frame, set as the app sets a new one.

func (*TextDrawer) DrawerType

func (*TextDrawer) DrawerType() string

DrawerType returns DrawerTypeText.

type TextOption

type TextOption interface {
	// contains filtered or unexported methods
}

TextOption sets something of the labels NewText and NewPages make. An Option is one.

type VerticalAlign

type VerticalAlign int

VerticalAlign is where a text box puts its lines down its frame. Each value was seen in the app, opening a file this package wrote. The app opened 3, and showed it as VerticalAlignMiddle, so it is not offered.

const (
	VerticalAlignTop    VerticalAlign = 0
	VerticalAlignMiddle VerticalAlign = 1
	VerticalAlignBottom VerticalAlign = 2
)

The alignments down.

func ParseVerticalAlign

func ParseVerticalAlign(name string) (VerticalAlign, error)

ParseVerticalAlign returns the alignment of a name: top, middle or bottom.

func (VerticalAlign) String

func (a VerticalAlign) String() string

String returns the name of a, as ParseVerticalAlign takes it.

func (VerticalAlign) Valid

func (a VerticalAlign) Valid() bool

Valid reports whether a is one of the alignments seen in the app.

Directories

Path Synopsis
cmd
tepra command
Command tepra makes .tm2 label files for TEPRA LINK 2.
Command tepra makes .tm2 label files for TEPRA LINK 2.

Jump to

Keyboard shortcuts

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