The Origami language is an expression language modeled after basic expressions in JavaScript.
Origami is focused on tasks like defining a website at a high level and can also be a useful scripting language. Towards those ends Origami deviates from JavaScript’s syntax in some places and omits many JavaScript features. This page enumerates the differences between Origami and JavaScript expressions.
Identifiers and references
Like JavaScript, Origami is a dynamic language; you do not need to specify the type of something when defining it.
- Unlike JavaScript variable declarations, defining something in Origami is implicit; you do not need to prefix a declaration with
let
orconst
. - In order to allow you to directly reference files by name, most file names are legal identifiers in Origami. For example,
index.html
is not a legal JavaScript identifier but is legal in Origami. - The following special characters in identifiers must be escaped with a
\
backslash:
(){}[]<>-=,/:`"'#→⇒
- Web URLs like
https://example.com
are valid references in Origami. - Scope in Origami is defined more broadly than in JavaScript. Code in a JavaScript module can only reference things outside the module via explicit
import
statements. Origami expressions can implicitly reference anything within a project.
Basic numbers but no math
Origami has signed integers and floating point numbers so that you can pass numeric values to functions. Beyond that:
- No binary, octal, hex, exponential notation
- No math operators
- No logical operators
- No bitwise operators
- No ternary operator
- No nullish coalescing operator
String literals
- Strings with double quotes and single quotes are essentially the same.
Template literals
- Expressions inside an Origami template placeholder can directly return complex values like arrays, objects, or trees. Origami will perform a depth-first traversal of the result and concatenate all the values into the final string result.
- Origami template literals do not support JavaScript’s tagged templates.
Array and object literals
Origami’s syntax for constructing array and object literals is essentially the same as JavaScript’s:
{
color: "Blue"
size: 20
values: [2, 4, 6]
}
- A newline can be used as an alternative separator instead of a comma in array literals, object literals, and tree literals (below).
- Trailing commas are allowed.
- An Origami object cannot define
get
orset
methods. (Although you can define a tree with members that behave likeget
methods; see below.) - An Origami object cannot define indirect property accessors. JavaScript in contrast allows accessors defined in
[ ]
square brackets. - To reference a specific object value in Origami, use
/
path syntax instead of JavaScript’s.
period. If the above object is available asobj
, thenobj/color
will be “Blue”. - Likewise, to reference a specific array value in Origami, use
/
path syntax instead of JavaScript’s[ ]
brackets. Hereobj/values/0
will be 2.
No control structures
As an expression language, Origami does not include any of JavaScript’s control structures like for
or while
loops.
Function calls
Function calls in Origami look similar to functions in JavaScript:
myFunction()
fn(a, b, c)
To use Origami to call a function defined in a JavaScript file, you must use the JavaScript file’s name, including the .js
(or .mjs
) extension:
greet.js("Alice")
Origami assumes that any function might be async
, so implicitly uses await
when calling them.
The Origami language runtime itself is written in JavaScript, so types described below such as numbers, strings, and objects are also the same.
Lambda functions
Origami supports a lambda function syntax similar to JavaScript’s:
(x) => fn(x)
Origami requires the parenthesis around the lambda parameters; JavaScript allows you to omit the parenthesis for a lambda with a single parameter.
For ease of use in a command shell with the Origami CLI, the language also supports a shorthand lambda syntax:
=fn x
This avoids the need to escape the >
greater than sign or ()
parentheses, which are typically interpreted by a shell.
Tree literals
For many operations, Origami converts all associative types — like arrays and objects — to an abstract tree structure. See the AsyncTree interface for details.
You can define a tree literal in Origami using a syntax that’s similar to an object literal, but where keys and values are separated with =
equal signs instead of :
colons:
{
index.html = createPage()
}
This type of Origami declaration will invoke the indicated expression — here, createPage()
— whenever the value of index.html
is retrieved. This behaves something like the JavaScript syntax for objects with get
methods:
/* JavaScript approximation of the above */
{
get indexDotHtml() { return createPage(); }
}
On difference is that the Origami example permits the createPage
function to be async
, while JavaScript prohibits the declaration of async
getters.
Implied exports and imports
Any Origami file with the .ori
extension will have its contents interpreted as an Origami expression. The result of this expression is implicitly exported and available from outside the file — unlike JavaScript, there is no need to explicitly export
a value.
This JavaScript:
// message.js
export default "This file exports this message.";
does the same thing as this message.ori
file, which implies a default export
:
"This file exports this message."
Likewise, because Origami scope includes the surrounding files, it is not necessary to explicitly import
values; you can directly refer to files by their names.
A JavaScript file might import the above message and incorporate it into an object with:
// console.js
import message from "./message.js";
export default {
"index.html": message,
};
An Origami file could do the same thing with:
{
index.html: message.ori/
}
Here the trailing /
slash is used to get the evaluated contents of message.ori
.