@hashml/hashml
HashML
HashML is a lightweight XML-like markup language, with built-in schema validation.
Installation
You can install HashML using npm by running
npm install @hashml/hashml
Example
Here is an example of a HashML document describing dinosaurs:
#dinosaur Tyrannosaurus rex
#emoji 🦖
A #link[Tyrannosaurus rex][https://en.wikipedia.org/wiki/Tyrannosaurus], a massive, meat-eating dinosaur with huge jaws, tiny arms, and a long tail.
It lived in the Late Cretaceous epoch.
#dinosaur Sauropod
#emoji 🦕
A #link[sauropod][https://en.wikipedia.org/wiki/Sauropoda], a massive, plant-eating dinosaur with a long neck and nail.
It lived in the Late Triassic to the Late Cretaceous epoch.
As a comparison, the equivalent XML would look like this:
<dinosaur>
<name>Tyrannosaurus rex</name>
<emoji>🦖</emoji>
<description>
<paragraph>A <link><title>Tyrannosaurus rex</title><url>https://en.wikipedia.org/wiki/Tyrannosaurus</url></link>, a massive, meat-eating dinosaur with huge jaws, tiny arms, and a long tail.</paragraph>
<paragraph>It lived in the Late Cretaceous epoch.</paragraph>
</description>
</dinosaur>
<dinosaur>
<name>Sauropod</name>
<emoji>🦕</emoji>
<description>
<paragraph>A <link><title>sauropod</title><url>https://en.wikipedia.org/wiki/Sauropoda</url></link>, a massive, plant-eating dinosaur with a long neck and nail.</paragraph>
<paragraph>It lived in the Late Triassic to the Late Cretaceous epoch.</paragraph>
</description>
</dinosaur>
The parser produces the following JSON:
{
"$tag": "root",
"dinosaurs": [
{
"$tag": "dinosaur",
"name": "Tyrannosaurus rex",
"meta": {
"$tag": "emoji",
"value": "🦖"
},
"description": [
{
"$tag": "paragraph",
"text": [
"A ",
{
"$tag": "link",
"title": "Tyrannosaurus rex",
"url": "https://en.wikipedia.org/wiki/Tyrannosaurus"
},
", a massive, meat-eating dinosaur with huge jaws, tiny arms, and a long tail."
]
},
{
"$tag": "paragraph",
"text": ["It lived in the Late Cretaceous epoch."]
}
]
},
{
"$tag": "dinosaur",
"name": "Sauropod",
...
}
]
}
HashML documents are parsed with a schema. The schema for the dinosaur descriptions would look like this:
#root
#body
#prop dinosaurs
#oneOrMore dinosaur
#block dinosaur
#default paragraph
#head
#string name
#body
#prop meta
#optional emoji
#prop description
#zeroOrMore paragraph
#block emoji
#head
#string value
#block paragraph
#head
#hashml
link
#inline link
#args
#string title
#url url
You can read more about the HashML schemas in the docs.
Usage
Compiling a schema to TypeScript
Use the CLI!
Parsing HashML files
To parse a HashML document from a Typescript program:
import { parse, ParsedSchema } from "@hashml/hashml";
const file = "#tag example";
const schemaFile = "#block tag"
const schemaSchemaFile = "#block block";
// Parse with a schema:
const schemaSchema = new ParsedSchema(parse(schemaSchemaFile));
const schema = new ParsedSchema(parse(schemaFile, schemaSchema));
const doc = parse(file, schema)
// ... or parse without a schema:
const noSchemaDoc = parse(file)
Parsing with a schema allows you to define syntactic sugar in the schema, like default elements and inline syntactic sugar.
To validate the document using the schema, use the validateBlock
method on the schema. This returns an array of validation errors. If there are no errors, it will return an empty array.
const errors = schema.validateBlock(doc);
To export the document to JSON or XML:
import { toXML, toJSON } from "@hashml/hashml";
const xml: string = toXML(doc);
const json: string = toJSON(doc);
CLI
See the @hashml/cli package.