Enables customization of tags and its objects in a few ways:
- Restrict and validates Metadata against a Schema
- Change how objects are indexed in the Object Index
- Tweak styling of tags in the editor using Space Style
success Success Put all your
tag.definecalls in your CONFIG page so that they will be picked up during the index process.
API
tag.define(spec)
Defines a tag explicitly.
spec is a table that can contain:
name(required) the name of the tagtagPagepage to navigate to when clicking the tag (defaults totag:name)metatableto set a custom Lua metatable for objects with this tag.mustValidatea boolean defining whether or not schema validation must pass for the object to be indexedschemaSchema to validate againstvalidatecallback function invoked when an objects needs to be validated, returnsnilor an error message.transformcallback function invoked when an object with tagnamehas been indexed. Allows you to make changes to it, skip indexing altogether or generate additional objects.
When tag.define is called multiple times with the same name, the specs will be merged. This e.g. enables overriding the schema of a built-in tag, or augment it with a custom transform callback.
This is a very powerful API, with a wide range of potential use cases.
Use cases
Schema validation
To define a Schema for validating an object (e.g. a page) tagged with #person ensuring that the age attribute is always a number, you can do the following:
tag.define {
name = "person",
-- mustValidate = true,
schema = {
type = "object",
properties = {
age = schema.number()
}
}
}Effect: When editing a page tagged with #person where this schema does not validate (e.g. you set the age to be a string), you will see this error being highlighted in the editor.
If you set mustValidate to true, schema validation will happen during the index phase (in addition to linting in the editor) and non-validating objects will not be indexed (with errors being reported in the JavaScript console). Use this to ensure all your objects conform to your schema (it does come at a slight performance penalty at the indexing phase). Errors are reported to the Log.
Index augmentation
Based on your page’s markdown, an indexer produces a list of objects to be indexed. If you define a transform callback function for a tag, this function will be invoked for each object with that tag, when the indexer encounters one. transform can inspect the object and do a few things:
- Make changes to the object in place and return it: this is the most common scenario. It allows you to attach additional attributes to the object before it’s persisted to the database.
- Return an empty table (
{}): in this case the object will not be indexed at all. - Return
nilin which case indexing proceeds as usual. - Return a list of objects that should be indexed instead: this may include the original object or a modification of it. This allows you to generate a set of custom objects, e.g. based on further parsing of the data in the object. A use case here could be to extract additional attributes from an existing attribute.
Note: one of the returned objects must have the same
refattribute as the object passed in.
warning Warning For custom
transformfunctions to be picked up during the initial client indexing phase they have to be defined in your CONFIG page.
note Note
transformwill only be invoked when a page is indexed. This generally happens after making a change. To apply newly definedtransformfunctionality to all pages in your space, you have to reindex the entire space usingSpace: Reindex.
Example: adding Page Decorations dynamically
The following dynamically adds a 🧑 prefix page decoration to all pages tagged with #person, such as John.
tag.define {
name = "person",
transform = function(o)
o.pageDecoration = { prefix = "🧑 " }
return o
end
}Example: a ‘deadline’ attribute for tasks
Let’s say that you’d like the encode a deadline attribute for tasks without using the [deadline: "2026-12-31"] syntax, instead you’d like to use an emoji as follows:
- Hello 📅 2026-12-31
In addition:
We’d like to highlight tasks that use a 📅 but then don’t follow the correct date format, like here:
- Hello task 📅 31-12-2026
And we’d like the name attribute to be cleaned from the deadline syntax.
This can be implemented by defining a custom transform for tasks:
local deadlinePattern = "📅%s*(%d%d%d%d%-%d%d%-%d%d)"
tag.define {
name = "task",
validate = function(o)
if o.name:find("📅") then
if not o.name:match(deadlinePattern) then
return "Found 📅, but did not match YYYY-mm-dd format"
end
end
end,
transform = function(o)
-- Use a regular expression to find a deadline
local date = o.name:match(deadlinePattern)
if date then
-- Remove the deadline from the name
o.name = o.name:gsub(deadlinePattern, "")
-- And put it in as attribute
o.deadline = date
end
return o
end
}The result is the following:
| name | done | deadline |
|---|---|---|
| Hello | false | 2026-12-31 |
Styling
Tags get assigned a data-tag-name attribute in the DOM, which you can use to do custom styling with Space Style.
Example: colorful tags
Example: my-red-tag
a[data-tag-name="my-red-tag"] {
background-color: red;
}