content
#In some cases, you might want to configure a snippet that is more complicated than the snippet templates provided for your SSG allow. Alternatively, you might be working with a syntax that CloudCannon doesn't provide templates for and you want to create your own snippet templates. In these cases, CloudCannon's underlying snippet parser can be configured directly.
Configuring snippets directly is more complicated than using snippet templates, but unlocks significantly more potential.
Snippet syntax#
Custom snippets are configured under the _snippets
key, and provide a snippet
string rather than a template
. If we were wanting to configure a custom snippet that matched bash variables like $HOME
or $PATH
, we might use the following config:
The snippet string contains the text to match for your snippet, with any dynamic sections represented using a placeholder in double square brackets.
In this example, the $
will match a literal $
character, and [[var_name]]
will use a specified parser.
For each placeholder, a matching key should be supplied inside the params
object. Here, [[var_name]]
maps to params.var_name
.
Each param needs to specify a parser
from the list of supported parsers. Here, the argument
parser is used for matching a single value.
Each parser requires a different set of options
. See the argument parser options for more details on this example.
The snippet string contains the text to match for your snippet, with any dynamic sections represented using a placeholder in double square brackets.
In this example, the $
will match a literal $
character, and [[var_name]]
will use a specified parser.
For each placeholder, a matching key should be supplied inside the params
object. Here, [[var_name]]
maps to params.var_name
.
Each param needs to specify a parser
from the list of supported parsers. Here, the argument
parser is used for matching a single value.
Each parser requires a different set of options
. See the argument parser options for more details on this example.
Parsers#
These are the parsers that a snippet can use:
argument
#Parses a single argument, optionally delimited by characters. Useful for matching a single positional argument.
The argument parser is also used to parse a list of repeating arguments.
argument_list
#Parses a list of distinct positional arguments based on their position.
key_values
#Parses repeating pairs of keys and values. Useful for most SSG snippets that take properties.
Can be configured to handle most syntax forms of key value pairs.
Parses rich multiline content, such as the content between paired tags. Can be configured to parse nested snippets within.
literal
#Parses an exact literal value. Mainly useful when configuring a snippet template.
repeating_literal
#Parses a repeating set of exact literal values.
optional
#Higher-order parser that wraps a snippet string and makes it optional.
repeating
#Higher-order parser that wraps a snippet string and allows it to repeat.
Argument parser#
Parses a single argument, optionally delimited by characters. Useful for matching a single positional argument.
Show exampleHide example
To illustrate the argument parser, we'll look at a custom video
snippet that takes a single named argument:
Options
Defines the parsing configuration for this argument.
Specifies the key that a user in CloudCannon will see when editing this value.
This key will also be used if you want to specify any input configuration using _inputs
.
Show exampleHide example
A list of valid values for the parser. If specified, values not in the provided list will cause this snippet to be skipped,
and a different snippet will be matched if possible.
A user entering a different value while editing this snippet will cause it to error, so this option is
best paired with a select input configured on the editor_key
.
Show exampleHide example
Example usage:
These IDs match a value in allowed_values
, thus will be shown as a video
snippet
This ID is not present in allowed_values
and will not parse as a video
snippet.
It may still parse as another snippet, or will remain as plain text.
The default value for this argument, which is used when adding a new snippet to a page in CloudCannon.
Show exampleHide example
With this config, adding a new video
snippet to a page in CloudCannon will instantiate it as <<video "riXoAr6gO-E">>
.
If implied_boolean
is set to true
, then any value in this argument will alias to true
, and an empty value will alias
to false
.
Show exampleHide example
With this config the video ID itself will not be used. The editor will instead see a checkbox named has_video_id
representing the presence of the argument. Unchecking and rechecking this checkbox will result in <<video true>>
,
so this option is not very useful for our video snippet example.
Whether a value must exist for this parser. Useful for a snippet that takes zero or one positional arguments.
Show exampleHide example
With this config, both of the following snippet examples will parse:
If true
, the output of this parser will be omitted entirely if the value is empty, rather than saving an empty value such as ""
.
In most cases, you will want to make sure to set optional: true
so that the output is able to be parsed again.
Show exampleHide example
In cases where you have a string boundary set, with this config saving a snippet with an
empty video_id
value will save it as <<video>>
rather than <<video "">>
or <<video ''>>
.
This should be an object containing keys from the available Format keys.
Show exampleHide example
A common option to configure for the
argument parser is the string_boundary
:
This would make our snippet match <<video "CZcNgDN81Sw">>
or <<video `CZcNgDN81Sw`>>
but not <<video 'CZcNgDN81Sw'>>
or <<video CZcNgDN81Sw>>
.
Another common requirement is specifying forbidden_tokens
,
especially when defining an argument with no string boundary.
This example sets the string boundary to nothing, with the intention of matching the source <<video CZcNgDN81Sw>>
.
Without specifying a forbidden token of >
, the above configuration would not match the Snippet,
as the argument parser is not able to determine the end of the argument.
Argument List parser#
This parser matches a list of positional arguments and parses each using a different model.
Instead of taking a single model
object, this parser takes an array of model
objects. Each model
object is an argument parser, but they all share one format
object.
Show exampleHide example
Continuing with our video
snippet shown above, we might add the ability to add a custom title as an optional second positional argument:
Since the title might contain whitespace, we want to make sure we set a string boundary of "
to capture each argument as intended.
Options
Defines the parsing configurations for each argument. Matches the model
options from the argument parser.
This should be an object containing keys from the available Format keys. These options will apply to all argument models.
Content parser#
The content parser is used to extract a block of content, optionally spread across multiple lines.
Usually this parser will be used to parse the content between paired start and end tags in a templating language.
Show exampleHide example
To illustrate the content parser, we'll look at a custom highlight
snippet that wraps a block of content:
Options
Specifies the key that a user in CloudCannon will see when editing this value.
This key will also be used if you want to specify any input configuration using _inputs
.
Show exampleHide example
With this config, the inner value of our snippet will be editable in CloudCannon
using an input named highlighted_text
, which we have configured as markdown
and specified a comment for.
Configures the content parser to require whitespace indentation when parsing. Used when a snippet continues for as long as content is indented.
This option should only be used if required, since it prevents your Snippet from parsing if the whitespace does not match. If you want parsing to be flexible, but the output to be formatted, use the Style options instead.
Show exampleHide example
Example usage:
This will parse correctly as My highlighted content!
This will strip only the indentation that matches, and return My highlighted content!
This will not match this parser, as indentation is required.
Use the style.block.indent
option instead.
If an indented_by
value is set, allow_leading: true
signifies that the first
line of the content does not need to be indented, but subsequent lines do.
Show exampleHide example
Example usage:
This will parse correctly as My highlighted content!
This will also parse correctly, as Some initial content\nMore highlighted content!
,
despite the first line not being indented.
If true, all whitespace and newlines will be trimmed from the start and end of the content before it is presented to an editor in CloudCannon.
Show exampleHide example
Example usage:
Both of these will parse as My highlighted content!
, despite the newlines and
whitespace surrounding them.
To add whitespace back in when outputting the snippet, use the Style options.
If set, nested snippets will be parsed and returned.
Show exampleHide example
Example usage:
With allow_nested
turned on, the content parser will detect and parse the nested
<<highlight>>
tags as another snippet, rather than plaintext.
This doesn't have to be the same snippet, any configured snippet will be parsed inside the content parser.
If allow_nested
is set to false, inner snippets will still be parsed, but will not be returned.
This means that in the above example, My highlighted <<highlight>>content!<</highlight>>
would
be the raw text with allow_nested: false
. If inner snippets were not parsed, the content parser
would end parsing at the first <</highlight>>
, giving you the text:
My highlighted <<highlight>>content!
. This is the behavior of the raw
option.
A stricter version of allow_nested: false
that performs no parsing of the inner text.
Useful to improve the performance of the content parser, but can misbehave.
Show exampleHide example
Example usage:
With raw
turned on, the content parser will perform no parsing on the text it is capturing.
This means that the nested <<highlight>>
will not be detected as a snippet and the first
<</highlight>>
tag found will end the content parser, giving you the parsed content
My highlighted <<highlight>>content!
.
Stops parsing content as soon as one of these tokens is encountered. Useful when the content parser is being greedy and consuming more input than intended.
Show exampleHide example
Example usage:
This snippet does not contain a forbidden token, so will parse and return correctly.
This snippet does contain a forbidden token, and will not match.
This isn't particularly useful in this example, but is generally used to prevent the content parser from consuming the end token of itself.
Whether content is required for this snippet to match.
A style object to control how content is parsed and stringified, to produce cleaner source code.
Show exampleHide example
For example, we'll look at the following input file:
As this snippet contains a single line of text, it will be formatted as inline
.
This snippet contains multiple lines, so will be auto-formatted as block
.
When the above file is opened in CloudCannon and saved, the source will be formatted to:
The inline
snippet was given the leading and trailing padding of the inline
style options.
The block
snippet was given the leading and trailing padding of the block
style options,
and was also indented by the provided tokens.
The style options are also stripped when the content editor loads a snippet, so the above
snippets would be edited as My content
and My\nmultiline\ncontent
respectively. As a result,
when using the style options you shouldn't need to configure the indented_by
option for the content parser.
Key values parser#
Parses repeating pairs of keys and values.
Show exampleHide example
To illustrate the Key values parser, we'll look at a custom anchor
snippet that parses the standard HTML anchor tag:
Options
Defines the parsing configurations for each argument.
Specifies the key that a user in CloudCannon will see when editing this value.
This key will also be used if you want to specify any input configuration using _inputs
.
If no source_key
is set, this key will also be assumed to be the source key.
Show exampleHide example
Key/value models can be specified in any order, so do not have to match the order of they keys in the source code.
Key/value models can be specified in any order, so do not have to match the order of they keys in the source code.
Example usage:
When edited in CloudCannon, this will edit as the data model:
Specifies the key that the parser should look for in the source text.
This only needs to be set if it differs from the editor_key
.
Show exampleHide example
Key/value models can be specified in any order, so do not have to match the order of they keys in the source code.
Key/value models can be specified in any order, so do not have to match the order of they keys in the source code.
Example usage:
When edited in CloudCannon, this will edit as the data model:
The default value for this argument, which is used when adding a new snippet to a page in CloudCannon.
Show exampleHide example
With this config, adding a new anchor
snippet to a page in CloudCannon will instantiate it
as <a href="/" target="_blank"> ... </a>
Whether a value must exist for this parser. Useful for long sets of key-value pairs that are not all required.
Show exampleHide example
Example usage:
All of these anchor tags will parse correctly, as they are missing either target
or class
keys from the arguments, and both are marked as optional
.
This anchor tag will not be parsed, as the href
key is absent and is not marked as optional
.
Whether this key-value pair should be omitted altogether if the value is empty. Requires that this key is also set as optional, as otherwise the snippet would not re-parse.
Show exampleHide example
Example usage:
With remove_empty: true
both of these anchor tags will be output as <a href="#link" target="_blank"> ... </a>
as the class
key contains no value.
If remove_empty: false
was set, this snippet would be output as <a href="#link" target="_blank" class=""> ... </a>
.
The empty class
key would be written even if it did not originally appear in the parsed source.
This should be an object containing keys from the available Format keys.
Literal parser#
Used to parse an exact literal value.
This parser is less useful when writing custom Snippets directly, but is very useful when writing Snippet templates.
Options
The exact literal string that should be matched.
Repeating literal parser#
Used to parse some number of repeating literal values.
Show exampleHide example
For this example, we'll pretend that we're making a Snippet for a markdown heading. This isn't something you need to do on CloudCannon since we understand Markdown natively, but it's a good illustration of the repeating literal parser.
Useful tip: Here we need to specify to the content parser that the value cannot contain newline characters, otherwise the content parser would consume the rest of the page.
Useful tip: Here we need to specify to the content parser that the value cannot contain newline characters, otherwise the content parser would consume the rest of the page.
Options
The exact literal string that should be matched.
The minimum number of times that the literal string must occur to match this parser. A good example is a markdown code block, which can open with any number of backticks greater than or equal to three.
Specifies a key that a user in CloudCannon will see to edit this value. The value returned by this parser is a number input that can be edited to change how many literals are output by the parser.
Show exampleHide example
Example usage:
If editing these as snippets in CloudCannon, the editor will see
heading_level
as a number input. Changing this value will
add or remove #
characters to the source code to match the number.
The default number of literals, which is used when adding a new snippet to a page in CloudCannon.
Optional parser#
Wraps a Snippet string, marking it as an optional segment of the Snippet.
Show exampleHide example
For this example, we'll look at configuring a Snippet for a theoretical custom internal link syntax. This syntax can handle linking to another page, and optionally lets you configure a custom label.
We can support this with the Snippet configuration:
Since this Snippet needs to match double square brackets in the source code, our template string here must escape them.
It's generally good practice to ensure non-delimited parsers have forbidden_tokens
configured to ensure they don't consume more input than intended.
This parser references a [[text]]
param, which is defined in the outer params object.
This text
param is only referenced from inside the optional parser's Snippet template string.
Since this Snippet needs to match double square brackets in the source code, our template string here must escape them.
It's generally good practice to ensure non-delimited parsers have forbidden_tokens
configured to ensure they don't consume more input than intended.
This parser references a [[text]]
param, which is defined in the outer params object.
This text
param is only referenced from inside the optional parser's Snippet template string.
Options
A snippet string to wrap and make optional.
This shares the same params as the outermost snippet, so may reference itself or other params.
Whether to output an empty string, or no value at all. This will bubble up to any outer parsers, so may control whether they return output.
Repeating parser#
Wraps a Snippet string, marking it as a repeating segment of the Snippet.
Useful when repeating a complex Snippet with multiple inputs. Simple arrays of primitive types should instead use the argument
parser configured as an array.
Show exampleHide example
For this example, we'll look at configuring a Snippet for a theoretical compound component that renders a block of links.
One option would be to configure a component for <Links>
that wraps a content editor, within which you can place <Link>
components.
This would work, but may expose too much functionality, for example we may not want editors to be able to type plain text between each <Link>
component.
Instead, we can define the following Snippet to handle the entire block as one component:
This parser references the [[link_args]]
and [[link_content]]
params, which are defined in the outer params object.
This style
object ensures that any Snippets are formatted to match the example Markdown above.
This parser references the [[link_args]]
and [[link_content]]
params, which are defined in the outer params object.
This style
object ensures that any Snippets are formatted to match the example Markdown above.
When edited in CloudCannon, the data will be extracted as:
Notice how each value is available under the editor_key
for its model,
and each repetition of the inenr snippet is then grouped inside the editor_key
set on the repeating parser.
Options
A snippet string to wrap and make repeatable.
This shares the same params as the outermost snippet, so may reference itself or other params.
The key to use when editing the data for this snippet in CloudCannon.
This key will become an array of objects, each containing the data for an iteration of the repeated snippet.
Used when initializing a new Snippet, and determines how many repetitions should be created in the initial data.
If false
this parser requires at least one matching value. If true
,
matching zero times is a valid state.
Setting this to true
is preferred to wrapping the repeating
parser inside an optional
parser.
A style object to control how content is parsed and stringified, to produce cleaner source code.
Can be customized to indent each repetition, add leading and trailing tokens to the entire block, and add tokens between each repetition.
Common style options#
Options to use when configuring how to save your Snippet back to your source file.
These options are flexible, and aren't required when parsing a Snippet. For example, this allows a Snippet to parse when it is found entirely on one line, but output across multiple lines with tidy indentation.
Either inline
or block
. For parsers such as the content and repeating parsers,
determines how to format the output.
When set to block
, values will always be output with leading and trailing newlines.
When set to inline
, values will always be output on a single line, with newlines inserted as \n
.
If unspecified, inline
will be chosen when the value is a single line, otherwise block
formatting will be used.
Used only in the repeating parser. Specifies the text to insert between each repetition. Useful for adding newlines between each repetition of the parser.
For inline content, what should lead the value. Useful for adding whitespace around strings.
For inline content, what should trail the value. Useful for adding whitespace around strings.
For block content, what should lead the value. Useful for adding newlines around content.
For block content, what should trail the value. Useful for adding newlines around content.
For block content, how should the value be indented. Nested snippets only need to specify the indentation relative to their parent.
Common format options#
Options to use when configuring how to parse your Snippet from your source file.
For key-value segments, what boundary is required (if any).
If a key-value segment is empty, but it has a root boundary, should that boundary be removed from the source code?
For key-value pairs, what delimits the key from the value.
- For pairs such as
key="value"
, this would be=
. - For pairs such as
key: "value"
, this would be:
.
For key-value pairs, what delimits the each key-value pair from the next.
- For segments such as
href="about" title="Hello World"
, this would be - For segments such as
href: about, title: "Hello World"
, this would be,
.
For arguments and values, what boundary is required (if any).
For example, MDX specifies { start: "{", end: "}" }
, which allows syntax such as: <Component flag={true} />
.
Where a root_value_boundary
applies, what types do not require a boundary?
For example, MDX specifies { string: true }
, which allows strings to exist as <Component arg="true" />
rather than <Component arg={"true"} />
.
The valid tokens that can bound a string. The parser will ensure the matched end token is the same as the start token.
To handle common strings with either single or double quotes, this would usually be ["'", "\""]
What character can be placed before a string boundary to escape it?
If required, this will usually be \
.
For snippets which can parse object literals, what characters start and end an object?
If required, this will usually be { start: "{", end: "}" }
.
Within an object, what delimits a key from a value?
If required, this will usually be :
.
Within an object, what delimits each key-value pair from the next.
If required, this will usually be ,
.
For snippets which can parse array literals, what characters start and end an array?
If required, this will usually be { start: "[", end: "]" }
.
Within an array, what delimits each value from the next"?
If required, this will usually be ,
.
For the given parser, what tokens are strictly not allowed in values. Most often used to limit what the content parser will consume.
Whether unquoted booleans like true
and false
can be used as values.
Whether unquoted numbers like 5
and -0.4
can be used as values.
When parsing key-value pairs, can a key be specified without a value to imply a value of true
?