# Inline scripts

> Run JavaScript inside Template and Capture choices with js quickadd code blocks, returning text or typed values to be inserted

An inline script is a small block of JavaScript you drop straight into a
[Template](/docs/Choices/TemplateChoice/) or
[Capture](/docs/Choices/CaptureChoice/) choice - or an
[AI Assistant prompt template](/docs/AIAssistant/#setup), which runs the same
format pass. When the choice runs, QuickAdd
runs your code and inserts whatever it returns, so you can compute the text
instead of typing it. Reach for one when a [placeholder](/docs/FormatSyntax/)
isn't enough: you need to transform what you typed, look something up, or build
text with a bit of logic.

## Write your first inline script {#write-your-first-inline-script}

Put a `js quickadd` code block anywhere in a template or capture format.
Whatever the script returns takes its place:

````
```js quickadd
const input = await this.quickAddApi.inputPrompt("✍");
return `Input given: ${input}`;
```
````

QuickAdd asks you for text, and inserts `Input given:` followed by whatever you
typed.

Good to know:

- Label the block `js quickadd`, not plain `js`. A plain `js` block is inserted as an ordinary code snippet and never runs.
- The [QuickAdd API](/docs/QuickAddAPI/) is available as `this` (the same API user scripts get, where it arrives as a parameter instead).
- To insert something, `return` it. Strings, numbers, booleans, and arrays are
  supported.

Return values follow the same rendering contract as a typed
[`{{VALUE:name}}`](/docs/FormatSyntax/#named-value):

| Return value | In ordinary text | As the sole value of a frontmatter property |
| --- | --- | --- |
| String | Inserted unchanged | Inserted unchanged |
| Number or boolean | Inserted as scalar text | Written as a Number or Checkbox value |
| Array | Joined with commas | Written as a native YAML list |
| `null` or `undefined` | Inserts nothing | Leaves the property empty |

Plain objects and other unsupported JavaScript values also insert nothing.
QuickAdd does not guess how to serialize them into Markdown. Assign an object to
`this.variables` and reference its fields explicitly, or return the exact string
you want to insert.

## Execution order and `{{VALUE}}` {#execution-order-and-value}

Inline scripts run *before* QuickAdd fills in unnamed placeholders like
`{{VALUE}}` and `{{NAME}}` in the surrounding output.

So if you write `let v = "{{VALUE}}"`, the script sees the literal text
`{{VALUE}}`, not your answer. Changing `v` changes that literal text, not the
value QuickAdd substitutes elsewhere.

When your script needs the real input, ask for it directly through the API and
work with what you get back:

````
```js quickadd
const raw = await this.quickAddApi.inputPrompt("Text");
if (!raw) return "";

const transformed = raw.toUpperCase();
this.variables.value = transformed; // optional handoff to formatter variables

return transformed;
```
````

Assigning `this.variables.value` hands the result back to the surrounding
format, so a later `{{VALUE}}` picks it up.

### Property Capture variables {#property-capture-variables}

In a [property Capture](/docs/Choices/CaptureChoice/#property), QuickAdd sets
these variables before your script runs. They are reserved for that run. Do not
also use `{{VALUE:propertyValue}}`, `{{VALUE:propertyKey}}`, or `{{VALUE:list}}`
in the same Capture.

| Variable | What it holds |
| --- | --- |
| `propertyValue` | The current value: text, a number, a checkbox, a list of text, or `undefined` when the property is missing |
| `propertyKey` | The property name being written |
| `list` | The current list items, or `[]` when the value is not a list |

This script adds one to a Number property:

````
```js quickadd
const n = Number(this.variables.propertyValue ?? 0);
return n + 1;
```
````

Return an array to rewrite the whole list. This script drops `old` and puts
`fresh` first:

````
```js quickadd
const kept = this.variables.list.filter((tag) => tag !== "old");
return ["fresh", ...kept];
```
````

To place the current value inside the format instead, use
[`{{PROPERTY}}`](/docs/FormatSyntax/#property).

### Example: convert phone text to a `tel:` link {#example-convert-phone-text-to-a-tel-link}

This script asks for a phone number, strips out spaces and punctuation, turns
any letters into their dial-pad digits, and returns a Markdown link:

````
```js quickadd
function convertPhoneNumberToLink(linkNumber) {
	linkNumber = linkNumber.replace(/[^a-zA-Z0-9+]/g, "");
	linkNumber = linkNumber.replace(/[ABCabc]/g, "2");
	linkNumber = linkNumber.replace(/[DEFdef]/g, "3");
	linkNumber = linkNumber.replace(/[GHIghi]/g, "4");
	linkNumber = linkNumber.replace(/[JKLjkl]/g, "5");
	linkNumber = linkNumber.replace(/[MNOmno]/g, "6");
	linkNumber = linkNumber.replace(/[PQRSpqrs]/g, "7");
	linkNumber = linkNumber.replace(/[TUVtuv]/g, "8");
	linkNumber = linkNumber.replace(/[WXYZwxyz]/g, "9");
	return `tel:${linkNumber}`;
}

const raw = await this.quickAddApi.inputPrompt("Phone number");
if (!raw) return "";

return `[${raw}](${convertPhoneNumberToLink(raw)})`;
```
````

Type `1-800-FLOWERS` and you get `[1-800-FLOWERS](tel:18003569377)`.