refactor: use a custom Link component to be able to use absolute URLs everywhere

...that supports any `base` property
This commit is contained in:
Joakim Carlstein 2023-12-19 09:57:23 +01:00
parent bdf831b008
commit ca6834d95f
21 changed files with 89 additions and 53 deletions

View file

@ -0,0 +1,11 @@
---
interface Props {
href: string;
}
const base = import.meta.env.BASE_URL === '/' || !import.meta.env.BASE_URL ? '' : import.meta.env.BASE_URL;
const site = import.meta.env.SITE ?? '';
const { href } = Astro.props;
---
<a href={`${site}${base}${href}`}><slot /></a>

View file

@ -4,6 +4,7 @@ description: "List migrations and their status."
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
The `list` command is used to list _all_ migrations, i.e. both already run migrations and migrations that haven't been run yet.
@ -51,7 +52,7 @@ The directory where the migration files are located. The given path should be ab
### `-s`, `--storage <name>`
The [storage plugin](../../plugins/storage/) to use, which is responsible for where to store the migration history.
The <Link href="/plugins/storage/">storage plugin</Link> to use, which is responsible for where to store the migration history.
The name can be either a path to a module or a package name. For package names Emigrate will automatically prefix the given name with these prefixes in order:
@ -67,7 +68,7 @@ In case you have both a `emigrate-storage-somedb` and a `somedb` package install
### `-r`, `--reporter <name>`
The reporter to use for listing the migrations.
The <Link href="/plugins/reporters/">reporter</Link> to use for listing the migrations.
The name can be either a path to a module or a package name. For package names Emigrate will automatically prefix the given name with these prefixes in order:

View file

@ -4,10 +4,11 @@ description: "Create new migration."
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
The `new` command is used to create a new migration file in the given directory.
The migration file can be based on a template, generated by a [generator plugin](../../plugins/generators/), or just be an empty file.
The migration file can be based on a template, generated by a <Link href="/plugins/generators/">generator plugin</Link>, or just be an empty file.
## Usage
@ -61,15 +62,15 @@ The directory where the migration files are located. The given path should be ab
The template file to use for generating the migration file. The given path should be absolute or relative to the current working directory.
The template can contain a `{{name}}` placeholder which will be replaced with the migration name provided to the command. The generated file will have the same extension as the template file, unless the [`--extension`](#e---extension-ext) option is used.
The template can contain a `{{name}}` placeholder which will be replaced with the migration name provided to the command. The generated file will have the same extension as the template file, unless the [`--extension`](#-e---extension-ext) option is used.
### `-e`, `--extension <ext>`
The extension to use for the migration file. Unless the [`--template`](#t---template-path) option is also specified the file will be empty.
The extension to use for the migration file. Unless the [`--template`](#-t---template-path) option is also specified the file will be empty.
### `-p`, `--plugin <name>`
The [generator plugin](../../plugins/generators/) to use. The generator plugin is responsible for generating the migration filename and its contents.
The <Link href="/plugins/generators">generator plugin</Link> to use. The generator plugin is responsible for generating the migration filename and its contents.
The name can be either a path to a module or a package name. For package names Emigrate will automatically prefix the given name with these prefixes in order:
@ -84,7 +85,7 @@ In case you have both a `emigrate-plugin-someplugin` and a `someplugin` package
### `-r`, `--reporter <name>`
The reporter to use for listing the migrations.
The <Link href="/plugins/reporters/">reporter</Link> to use for listing the migrations.
The name can be either a path to a module or a package name. For package names Emigrate will automatically prefix the given name with these prefixes in order:

View file

@ -4,6 +4,7 @@ description: "Remove a migration from the history."
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
The `remove` command is used to remove a migration from the history. This is useful if you want to retry a migration that has failed.
@ -58,7 +59,7 @@ Force removal of the migration history entry even if the migration file does not
### `-s`, `--storage <name>`
The [storage plugin](../../plugins/storage/) to use, which is responsible for where to store the migration history.
The <Link href="/plugins/storage/">storage plugin</Link> to use, which is responsible for where to store the migration history.
The name can be either a path to a module or a package name. For package names Emigrate will automatically prefix the given name with these prefixes in order:
@ -74,7 +75,7 @@ In case you have both a `emigrate-storage-somedb` and a `somedb` package install
### `-r`, `--reporter <name>`
The reporter to use for listing the migrations.
The <Link href="/plugins/reporters/">reporter</Link> to use for listing the migrations.
The name can be either a path to a module or a package name. For package names Emigrate will automatically prefix the given name with these prefixes in order:

View file

@ -4,6 +4,7 @@ description: "Run migrations"
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
The `up` command is used to either list or run all pending migrations, i.e. migrations that haven't been run yet.
@ -57,7 +58,7 @@ The directory where the migration files are located. The given path should be ab
### `-s`, `--storage <name>`
The [storage plugin](../../plugins/storage/) to use, which is responsible for where to store the migration history.
The <Link href="/plugins/storage/">storage plugin</Link> to use, which is responsible for where to store the migration history.
The name can be either a path to a module or a package name. For package names Emigrate will automatically prefix the given name with these prefixes in order:
@ -73,7 +74,7 @@ In case you have both a `emigrate-storage-somedb` and a `somedb` package install
### `-p`, `--plugin <name>`
The [loader plugin(s)](../../plugins/loaders/) to use. Can be specified multiple times to use multiple plugins.
The <Link href="/plugins/loaders/">loader plugin(s)</Link> to use. Can be specified multiple times to use multiple plugins.
The name can be either a path to a module or a package name. For package names Emigrate will automatically prefix the given name with these prefixes in order:
@ -88,7 +89,7 @@ In case you have both a `emigrate-plugin-someplugin` and a `someplugin` package
### `-r`, `--reporter <name>`
The reporter to use for reporting the migration progress.
The <Link href="/plugins/reporters/">reporter</Link> to use for reporting the migration progress.
The name can be either a path to a module or a package name. For package names Emigrate will automatically prefix the given name with these prefixes in order:

View file

@ -17,6 +17,7 @@ hero:
---
import { Card, CardGrid } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
## Key features
@ -29,10 +30,10 @@ import { Card, CardGrid } from '@astrojs/starlight/components';
Migrate many databases from one repository or many repositories to one database. There's no need to synchronize deployments.
</Card>
<Card title="SQL, JavaScript, TypeScript, etc." icon="document">
Write your migration files using the [language of your choice](plugins/loaders/).
Write your migration files using the <Link href="/plugins/loaders/">language of your choice</Link>.
And mix and match them as you need. E.g. `SQL` for database schema changes, and `JavaScript` for data transformation.
</Card>
<Card title="Customize to your setup" icon="puzzle">
Emigrate is designed to be flexible and customizable to suite any environment and setup using its [plugin system](plugins/).
Emigrate is designed to be flexible and customizable to suite any environment and setup using its <Link href="/plugins/">plugin system</Link>.
</Card>
</CardGrid>

View file

@ -4,6 +4,7 @@ description: Get going with Emigrate quickly
---
import { Tabs, TabItem, LinkCard } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
:::note
The following guide will be even simpler soon with the release of a initialization command.
@ -38,7 +39,7 @@ But for now, this is the way to go.
### Pick a storage plugin
Emigrate uses a [storage plugin](../../plugins/storage/) to store the migration history.
Emigrate uses a <Link href="/plugins/storage/">storage plugin</Link> to store the migration history.
Install the plugin you want to use, for example:
@ -84,7 +85,7 @@ Otherwise the file would have the `.js` extension by default.
:::tip[Did you know?]
You can avoid typing `--plugin mysql` by configuring Emigrate using an `emigrate.config.js` file.
See [Configuration](../../reference/configuration/) for more information.
See <Link href="/reference/configuration/">Configuration</Link> for more information.
:::
#### Fill the migration file
@ -132,7 +133,7 @@ npx emigrate up --storage mysql --plugin mysql --dry
```
:::note
This will connect to the database using some default values. For ways to configure the connection, see [Configuration](../../reference/configuration/).
This will connect to the database using some default values. For ways to configure the connection, see <Link href="/reference/configuration/">Configuration</Link>.
:::
:::caution
@ -141,6 +142,6 @@ Be sure to configure the connection correctly and use the `--dry` flag to test y
:::
:::tip[Did you know?]
In the example above the `@emigrate/mysql` plugin is used twice, once for the `--storage` option as a [Storage Plugin](../../plugins/storage/)
and once for the `--plugin` option as a [Loader Plugin](../../plugins/loaders/) to be able to read `.sql` files.
In the example above the `@emigrate/mysql` plugin is used twice, once for the `--storage` option as a <Link href="/plugins/storage/">Storage Plugin</Link>
and once for the `--plugin` option as a <Link href="/plugins/loaders/">Loader Plugin</Link> to be able to read `.sql` files.
:::

View file

@ -3,15 +3,17 @@ title: What's Emigrate?
description: An introduction to Emigrate, the modern database agnostic migration tool.
---
import Link from '@components/Link.astro';
Emigrate is written in [TypeScript](https://www.typescriptlang.org) and is a migration tool for any database or data.
* It's database agnostic - you can use it with any database, or even with non-database data.
* It's the successor of [klei-migrate](https://github.com/klei/migrate) and is designed to be compatible with [Immigration](https://github.com/blakeembrey/node-immigration) and many of its storage plugins, as well as [Migrate](https://github.com/tj/node-migrate).
* It supports migration files written using [CommonJS or ES Modules out of the box](../../plugins/loaders/default/), with any of the following extensions: `.js`, `.cjs` or `.mjs`, and supports [async functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function), [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or using the [NodeJS Callback Pattern](https://nodejs.org/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks#handling-errors-in-callbacks).
* Other languages can be used by using a [Loader Plugin](../../plugins/loaders/).
* The migration history can be stored anywhere using a [Storage Plugin](../../plugins/storage/).
* The output can be customized using [Reporters](../../plugins/reporters/).
* It supports migration files written using <Link href="/plugins/loaders/default/">CommonJS or ES Modules out of the box</Link>, with any of the following extensions: `.js`, `.cjs` or `.mjs`, and supports [async functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function), [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or using the [NodeJS Callback Pattern](https://nodejs.org/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks#handling-errors-in-callbacks).
* Other languages can be used by using a <Link href="/plugins/loaders/">Loader Plugin</Link>.
* The migration history can be stored anywhere using a <Link href="/plugins/storage/">Storage Plugin</Link>.
* The output can be customized using <Link href="/plugins/reporters/">Reporters</Link>.
:::tip[Did you know?]
Thanks to [the plugin system](../../plugins/) you can even write migrations in plain SQL! So no need for Java-based tools like Liquibase or Flyway.
Thanks to <Link href="/plugins/">the plugin system</Link> you can even write migrations in plain SQL! So no need for Java-based tools like Liquibase or Flyway.
:::

View file

@ -3,12 +3,13 @@ title: "Generator Plugins"
---
import { LinkCard, CardGrid } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
A generator plugin is a plugin that generates new migration files.
They are responsible for both generating the new file's name and its contents.
:::tip[Did you know?]
Many of the [Loader Plugins](../loaders/) usually include a generator plugin as well.
Many of the <Link href="/plugins/loaders/">Loader Plugins</Link> usually include a generator plugin as well.
The generator is responsible for generating migration files in a specific format and the loader is responsible for loading the same format.
:::
@ -20,5 +21,5 @@ The generator is responsible for generating migration files in a specific format
</CardGrid>
:::note
Instead of having to install a generator plugin, you can also use the much simpler [`--template`](../../commands/new/#t---template-path) option to specify a custom template file for new migrations.
Instead of having to install a generator plugin, you can also use the much simpler <Link href="/commands/new/#-t---template-path">`--template`</Link> option to specify a custom template file for new migrations.
:::

View file

@ -3,8 +3,9 @@ title: "JavaScript Generator"
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
A [generator plugin](../) for generating new migration files in JavaScript.
A <Link href="/plugins/generators/">generator plugin</Link> for generating new migration files in JavaScript.
## Installation
@ -32,4 +33,4 @@ A [generator plugin](../) for generating new migration files in JavaScript.
emigrate new --plugin generate-js create some fancy table
```
For more information see [the `new` command](../../commands/new/)'s documentation.
For more information see <Link href="/commands/new/">the `new` command</Link>'s documentation.

View file

@ -3,8 +3,9 @@ title: "MySQL Generator"
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
The MySQL generator creates new migration files with the `.sql` extension. In the same package you can find the [MySQL Loader](../../loaders/mysql/) and the [MySQL Storage](../../storage/mysql/).
The MySQL generator creates new migration files with the `.sql` extension. In the same package you can find the <Link href="/plugins/loaders/mysql/">MySQL Loader</Link> and the <Link href="/plugins/storage/mysql/">MySQL Storage</Link>.
## Installation
@ -32,4 +33,4 @@ The MySQL generator creates new migration files with the `.sql` extension. In th
emigrate new --plugin mysql create some fancy table
```
For more information see [the `new` command](../../../commands/new/)'s documentation.
For more information see <Link href="/commands/new/">the `new` command</Link>'s documentation.

View file

@ -3,10 +3,11 @@ title: Loader Plugins
---
import { LinkCard, CardGrid } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
Loader plugins are used to transform any file type into a JavaScript function that will be called when the migration file is executed.
Out of the box, Emigrate supports the following file extensions: `.js`, `.cjs` and `.mjs`. And both CommonJS and ES Modules are supported. See the [Default Loader](default/) for more information.
Out of the box, Emigrate supports the following file extensions: `.js`, `.cjs` and `.mjs`. And both CommonJS and ES Modules are supported. See the <Link href="/plugins/loaders/default/">Default Loader</Link> for more information.
## Using a loader plugin
@ -16,12 +17,12 @@ You can specify a loader plugin via the `--plugin` (or `-p` for short) option:
npx emigrate up --plugin mysql
```
Or set it up in your configuration file, see [Plugin configuration](../../reference/configuration/#plugins) for more information.
Or set it up in your configuration file, see <Link href="/reference/configuration/#plugins">Plugin configuration</Link> for more information.
:::tip[Did you know?]
You can specify multiple loader plugins at the same time, which is needed when you mix file types in your migrations folder.
For example, you can use the `mysql` loader for `.sql` files and the `typescript` loader for `.ts` files.
The [default loader](default/) will be used for all other file types, and doesn't need to be specified.
The <Link href="/plugins/loaders/default/">default loader</Link> will be used for all other file types, and doesn't need to be specified.
:::
## Available Loader Plugins

View file

@ -3,8 +3,9 @@ title: MySQL Loader Plugin
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
The MySQL loader plugin transforms `.sql` files into JavaScript functions that Emigrate can use to execute the migrations. In the same package you can find the [MySQL Generator](../../generators/mysql/) and the [MySQL Storage](../../storage/mysql/).
The MySQL loader plugin transforms `.sql` files into JavaScript functions that Emigrate can use to execute the migrations. In the same package you can find the <Link href="/plugins/generators/mysql/">MySQL Generator</Link> and the <Link href="/plugins/storage/mysql/">MySQL Storage</Link>.
## Installation
@ -28,7 +29,7 @@ The MySQL loader plugin transforms `.sql` files into JavaScript functions that E
## Configuration
The MySQL loader plugin can be configured either using environment variables or by configuring the plugin directly in the [`emigrate.config.js` file](../../../reference/configuration/).
The MySQL loader plugin can be configured either using environment variables or by configuring the plugin directly in the <Link href="/reference/configuration/">`emigrate.config.js` file</Link>.
### Configuration file
@ -76,7 +77,7 @@ The environment variables are used when the plugin is used using the `--plugin`
npx emigrate list --plugin mysql
```
Or when specifying the plugin in the [`emigrate.config.js` file](../../../reference/configuration) as a string:
Or when specifying the plugin in the <Link href="/reference/configuration/">`emigrate.config.js` file</Link> as a string:
```js title="emigrate.config.js" {2}
export default {

View file

@ -3,6 +3,7 @@ title: Reporters
---
import { LinkCard, CardGrid } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
A reporter is a plugin that's responsible for printing the migration progress and results to the console.
@ -14,7 +15,7 @@ You can specify a reporter via the `--reporter` (or `-r` for short) option:
npx emigrate list --reporter pino
```
Or set it up in your configuration file, see [Reporter configuration](../../reference/configuration/#reporter) for more information.
Or set it up in your configuration file, see <Link href="/reference/configuration/#reporter">Reporter configuration</Link> for more information.
## Available Reporters

View file

@ -3,6 +3,7 @@ title: Pino Reporter
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
Emigrate's reporter that uses [Pino](https://getpino.io/#/) as the logger.
@ -40,7 +41,7 @@ The `@emigrate/reporter-` prefix is optional when using this reporter.
emigrate <command> --reporter pino
```
See for instance the [Reporter Option](../../../commands/up/#-r---reporter-name) for the `up` command for more information.
See for instance the <Link href="/commands/up/#-r---reporter-name">Reporter Option</Link> for the `up` command for more information.
### Via configuration file
@ -50,7 +51,7 @@ export default {
};
```
See [Reporter Configuration](../../../reference/configuration/#reporter) for more information.
See <Link href="/reference/configuration/#reporter">Reporter Configuration</Link> for more information.
## Example output

View file

@ -3,6 +3,7 @@ title: File System Storage
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
The File System Storage is a storage driver that stores the migration history in a `.json` file on the local file system.
@ -32,7 +33,7 @@ This is suitable for simple setups, but for more advanced setups for instance wh
## Configuration
The File System Storage can be configured easily in your [`emigrate.config.js` file](../../reference/configuration/):
The File System Storage can be configured easily in your <Link href="/reference/configuration/">`emigrate.config.js` file</Link>:
```js {1,4-6}
import storageFs from '@emigrate/storage-fs';

View file

@ -3,6 +3,7 @@ title: Storage Plugins
---
import { LinkCard, CardGrid } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
Storage plugins are used for storing and reading the migration history state.
Usually you'll want to store the migration history in the same database as the one which your migration files are targeting.
@ -15,7 +16,7 @@ You can specify a storage plugin via the `--storage` (or `-s` for short) option:
npx emigrate list --storage mysql
```
Or set it up in your configuration file, see [Storage configuration](../../reference/configuration/#storage) for more information.
Or set it up in your configuration file, see <Link href="/reference/configuration/#storage">Storage configuration</Link> for more information.
## Available storage plugins
@ -29,5 +30,5 @@ More storage plugins are coming soon!
:::
:::tip[Is your database missing?]
Writing a storage plugin is easy! Check out the [Storage Plugin API](../../reference/storage-plugin-api/) for more information.
Writing a storage plugin is easy! Check out the <Link href="/reference/storage-plugin-api/">Storage Plugin API</Link> for more information.
:::

View file

@ -3,8 +3,9 @@ title: MySQL Storage
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
The MySQL storage plugin uses a MySQL database to store the migration history (*duh*). In the same package you can find the [MySQL Loader](../../loaders/mysql/) and the [MySQL Generator](../../generators/mysql/).
The MySQL storage plugin uses a MySQL database to store the migration history (*duh*). In the same package you can find the <Link href="/plugins/loaders/mysql/">MySQL Loader</Link> and the <Link href="/plugins/generators/mysql/">MySQL Generator</Link>.
## Installation
@ -28,7 +29,7 @@ The MySQL storage plugin uses a MySQL database to store the migration history (*
## Configuration
The MySQL storage can be configured either using environment variables or by configuring the plugin directly in the [`emigrate.config.js` file](../../../reference/configuration/).
The MySQL storage can be configured either using environment variables or by configuring the plugin directly in the <Link href="/reference/configuration/">`emigrate.config.js` file</Link>.
### Configuration file
@ -83,7 +84,7 @@ The environment variables are used when the storage plugin is used using the `--
npx emigrate list --storage mysql
```
Or when specifying the storage in the [`emigrate.config.js` file](../../../reference/configuration) as a string:
Or when specifying the storage in the <Link href="/reference/configuration/">`emigrate.config.js` file</Link> as a string:
```js title="emigrate.config.js" {2}
export default {

View file

@ -6,6 +6,7 @@ sidebar:
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import Link from '@components/Link.astro';
Emigrate can be configured using a configuration file, and it uses [Cosmiconfig](https://github.com/cosmiconfig/cosmiconfig) under the hood
so you can use a variety of formats and locations for your configuration file.
@ -47,7 +48,7 @@ Set the directory where your migrations are located, relative to the project roo
**type:** `string | EmigrateReporter | Promise<EmigrateReporter> | (() => Promise<EmigrateReporter>)`
**default:** `"default"` - the default reporter
Set the reporter to use for the different commands. Specifying a [reporter](../plugins/reporters/) is most useful in a CI or production environment where you either ship logs or want to have a machine-readable format.
Set the reporter to use for the different commands. Specifying a <Link href="/plugins/reporters/">reporter</Link> is most useful in a CI or production environment where you either ship logs or want to have a machine-readable format.
```js title="emigrate.config.js" {2}
export default {
@ -77,7 +78,7 @@ The default reporter automatically detects if the current environment is an inte
**type:** `string | EmigrateStorage | Promise<EmigrateStorage> | (() => Promise<EmigrateStorage>)`
Set the [storage plugin](../plugins/storage/) to use for storing and reading the migration history. This option is required by all Emigrate commands except `new` which doesn't use it.
Set the <Link href="/plugins/storage/">storage plugin</Link> to use for storing and reading the migration history. This option is required by all Emigrate commands except `new` which doesn't use it.
```js title="emigrate.config.js" {2}
export default {
@ -86,7 +87,7 @@ export default {
```
:::note
Each storage plugin can have its own configuration options, see the corresponding [Storage Plugin](../plugins/storage/) section for more information.
Each storage plugin can have its own configuration options, see the corresponding <Link href="/plugins/storage/#available-storage-plugins">Storage Plugin</Link> section for more information.
:::
### `plugins`
@ -97,8 +98,8 @@ Set the plugins to use for the different commands. There are different types of
In short:
* [Loader Plugins](../plugins/loaders/) - are used for transforming non-JavaScript files into JavaScript files that can be executed by Node.js. These are only used by the `up` command.
* [Generator Plugins](../plugins/generators/) - are used for generating new migration files. These are only used by the `new` command.
* <Link href="/plugins/loaders/">Loader Plugins</Link> - are used for transforming non-JavaScript files into JavaScript files that can be executed by Node.js. These are only used by the `up` command.
* <Link href="/plugins/generators/">Generator Plugins</Link> - are used for generating new migration files. These are only used by the `new` command.
```js title="emigrate.config.js" {2}
export default {
@ -107,7 +108,7 @@ export default {
```
:::tip[Did you know?]
The same package can expose multiple plugins, so you can specify the plugin only once and it can be used as both a loader and a generator (and storage, in the case of [MySQL](../plugins/storage/mysql) for instance).
The same package can expose multiple plugins, so you can specify the plugin only once and it can be used as both a loader and a generator (and storage, in the case of <Link href="/plugins/storage/mysql/">MySQL</Link> for instance).
:::
### `template`