napkin-sketchdocs 1.0.0 GitHub

The napkin script language: cheatsheet#

On this page

API hub · Reference · Quickstart · Cheatsheet

Reminders for the language: syntax, values, the verbs that shape a script, functions, the budget and every diagnostic code.

Syntax#

WriteMeans
napkin 1The first line: the language version. Without it, a version-missing warning.
line 0 0 10 10; line 10 10 20 0, color #1f2328 width 3One instruction a line - the verb, then its arguments - or several with ; between; paint verbs share a line, nothing else does.
group "Figure" { ... }A block, for group, clip, define, repeat, wipe, stack and path.
# a comment, RECT# and a space comments to the end of the line (#note with no space is read as an argument); verbs, keywords and choices ignore case.

Values#

KindTextJSON
Number12, -3.5, 1e312
Length120, 10mm, 0.5in, 12pt, 4px, 50%120, "10mm", "50%"
Expression, anywhere a number or a length goes(width / 2), (i * 40 + 20){ "expr": "width / 2" }
String"Acme Corp", "one\ntwo""Acme Corp"
Color; switch#1f2328, steelblue, rgb(31, 35, 40); on, off"#1f2328"; true, false
Points; stops0 0, 10 0, 5 8; (#ffffff 0, #000000 1)[{ "x": 0, "y": 0 }, ...]; [{ "color": "#ffffff", "offset": 0 }, ...]

The verbs that shape a script#

CategoryVerbWrittenDoes
Documentnapkinnapkin <version>The language version the script was written for. The first line of a script; without it version 1 is assumed, with a warning.
Documentpagepage <paper> [portrait|landscape]
page <width> <height> [portrait|landscape]
The page size: a named size (a3, a4, a5, letter, legal, tabloid, square, slide, napkin) or a width and a height, turned portrait or landscape.
Documentbackgroundbackground <color>
background none
The page color, or none for a transparent page.
Documentnamename "<name>"The page's name, and the file stem it is written under.
Documentunitsunits px|in|mm|ptThe unit bare numbers are read in from here on: px, in, mm or pt. Pixels until changed.
Documentseedseed <n>The seed for the hand-drawn pass. One script and one seed draw the same bytes every run.
Documentnewpagenewpage ["<name>"]Starts another page the same size, carrying the paint state across.
TransformspushpushSaves the transform, the paint state and the units, for the next pop to restore.
TransformspoppopRestores the transform, the paint state and the units the last push saved.
Transformstranslatetranslate <dx> <dy>Moves everything drawn after it.
Transformsrotaterotate <degrees> [at <x> <y>]Turns everything drawn after it, clockwise in degrees, about the origin or a point given with at.
Transformsscalescale <s> [<sy>] [at <x> <y>]Scales everything drawn after it, about the origin or a point given with at. One factor scales both ways.
Transformsmirrormirror x|y [at <position>]Reflects everything drawn after it: x swaps left and right across a vertical line, y swaps top and bottom across a horizontal one, at 0 unless given.
Controlletlet <name> <value>Names a number for the expressions after it, in the current units.
Controldefinedefine "<name>" { ... }Records a block of drawing under a name without drawing it, for place to draw.
Controlplaceplace "<name>" [at <x> <y>] [scale <s>] [rotate <degrees>]Draws a definition, moved, scaled or turned.
Controlrepeatrepeat <count> [as <name>] { ... }Runs a block a number of times, counting from 0 in the name given with as.

Functions#

FunctionTakesGives
sina numberThe sine of an angle in degrees.
cosa numberThe cosine of an angle in degrees.
tana numberThe tangent of an angle in degrees.
sqrta numberThe square root.
absa numberThe value without its sign.
rounda numberThe nearest whole number.
floora numberThe whole number at or below.
ceila numberThe whole number at or above.
min2 or more numbersThe smallest of two or more values.
max2 or more numbersThe largest of two or more values.

The budget#

LimitDefaultCounts
instructions200,000Instructions run, every pass through a repeat counted
marks50,000Marks drawn
anchors250,000Bezier anchors, across every mark
points1,000,000Points sampled from those anchors for the canvas to paint
depth64Blocks open at once: groups and clips, placed definitions, repeats, wipes and stacks

In code#

CallGives
parseScript(text), validateScript(json); formatScript(script), formatDiagnostic(d, 'card.napkin'){ ok, script, diagnostics } from text or the object form ({ fragment } for a piece of one), never throwing; the script as canonical text, and a diagnostic as card.napkin:3:1: error unknown-verb: ...

Diagnostic codes#

CodeLevelMeaning
unknown-verberrorA line starts with a word that is not a verb.
misplaced-verberrorA verb where it cannot appear: a path step outside a path block, a napkin line after the first, a layer inside a path, a newpage inside a group or a definition, a layer, group, clip or use inside a wipe or a stack.
unsupported-verberrorThe verb, or this way of writing it, is known but not drawn by this build or by the host running the script; the instruction is skipped.
expected-numbererrorA number, or an expression in parentheses, was expected.
expected-lengtherrorA length was expected: a number, a number with a unit (10mm, 0.5in, 12pt, 4px), a percentage, or an expression.
expected-stringerrorA double-quoted string was expected.
expected-identifiererrorA bare name was expected: letters, digits and underscores, starting with a letter.
expected-colorerrorA CSS color was expected, such as #1f2328, red or rgb(31, 35, 40).
expected-choiceerrorOne word from a fixed list was expected; the message lists them.
expected-pointserrorA list of points was expected: x y pairs separated by commas.
expected-stopserrorA list of gradient stops was expected: (color offset, color offset, ...).
unexpected-tokenerrorSomething is left on the line after the instruction was read, or a character that cannot start anything.
missing-argumenterrorA required argument is missing; the message names it and shows how the verb is written.
expected-blockerrorA block was expected: { at the end of the line, the instructions it holds, and } to close it.
unclosed-blockerrorA block opened with { is never closed with }.
unexpected-closeerrorA } closes a block that was never opened.
unclosed-stringerrorA string runs to the end of the line without its closing quote.
invalid-expressionerrorAn expression could not be read: an unknown operator, a missing operand, or an unclosed parenthesis.
unit-unknownerrorA number carries a unit the language does not know. The units are px, in, mm and pt, and % for a share of the page.
invalid-valueerrorA value is out of range: an opacity above 1, a negative radius, a star with fewer than 2 points, a percentage where the page cannot measure one.
version-missingwarningThe script does not start with napkin <version>; version 1 is assumed.
version-unsupportederrorThe script names a version newer than this build reads; the message names the newest it does.
unknown-variableerrorAn expression uses a name no let or repeat has set.
unknown-definitionerrorplace names something no define recorded.
unknown-shapeerrorshape names something the shape library does not have.
unknown-asseterrorimage names an asset the host did not supply.
unknown-documenterroruse names a document the host did not supply.
unknown-configerrorconfig names a Text Configuration no textconfig before it defined.
image-size-unknownwarningAn image's size cannot be read from its data, so it is placed square: 100 by 100, or the one size given by itself.
glyph-missingwarningtext as marks has a character the built-in face does not draw; it is left as a gap.
unknown-fieldwarningAn instruction in a JSON script has a field its verb does not have; it is left out.
recursive-definitionerrorA definition places itself, directly or through another definition.
division-by-zeroerrorAn expression divides by zero.
budget-exceedederrorThe script ran more instructions, drew more marks, emitted more anchors or sampled points, or nested deeper than the limit allows; what it drew up to that point is kept.
pop-without-pusherrorpop with nothing saved to restore.
unbalanced-pushwarningA push is never popped before its block ends; the saved state is restored there anyway.
duplicate-definitionwarningA second define replaces an earlier one of the same name.
link-unresolvedwarningA linked file could not be read for an output that has to draw it, so its placeholder was drawn instead.
unused-effectwarningAn effect nothing took: no layer, group or mark followed it before its block, its page or the script ended.
unused-blendwarningA blend nothing took: no layer or group followed it before another blend, its block, its page or the script ended. A blend is a layer's, so a mark alone does not take it.
unused-accentwarningAn accent nothing took: no text followed it before another accent, its block, its page or the script ended, or the text was drawn as marks.
wipe-skippedwarningA wipe's or a stack's block drew marks it cannot combine - text, pictures, linked files, eraser marks - and they are drawn as they are.
wipe-emptywarningA wipe or a stack left nothing: out-front's bottom mark wholly covered by the rest, say, or a stack remove taking every piece.
wipe-failedwarningA wipe or a stack could not combine its block's marks - fewer than two it can combine, more than it takes, or geometry it could not make - so they are drawn as they are.
stack-missedwarningA stack point is on none of the pieces its block's marks make, so it picks nothing; the message says which.
split-missedwarningA split point is within 4 px of no path drawn so far, or lands on the end of an open one, so nothing is cut.
clip-openwarningA clip block drew no closed shape to clip with, so it is a plain group.
smear-missedwarningA smear reaches no pencil mark drawn so far, so it spreads nothing.
liquify-missedwarningA warp, twirl, pucker or bloat reaches no mark it bends drawn so far, so it bends nothing.
erase-skippedwarningAn eraser line reaches text or a picture, which it cannot cut, and passes over it.

Common mistakes#

WrongRightWhy
circle i*40 50 gapcircle (i * 40) 50 (gap)Arithmetic goes in parentheses, and so does a name where a number goes.
A script with no napkin 1napkin 1 firstA version-missing warning, which --strict fails.