Skip to content

Commit 077af63

Browse files
authored
Documentation Update & Demo Template
Documentation Update & Demo Template
2 parents 6712030 + b6eb3f0 commit 077af63

File tree

10 files changed

+877
-140
lines changed

10 files changed

+877
-140
lines changed

DEMO_TEMPLATE.md

Lines changed: 490 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 312 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
This plugin allows you to create templates in Joplin and use them to create new notes and to-dos.
1212

13+
> **📚 New to the plugin?** Check out the [Complete Feature Demonstration Template](DEMO_TEMPLATE.md) to see all features in action with examples and expected outputs.
14+
1315
## Table of contents
1416

1517
- [Installing Plugin](#installing-plugin)
@@ -23,7 +25,16 @@ This plugin allows you to create templates in Joplin and use them to create new
2325
- [Custom variables](#custom-variables)
2426
- [Advanced Usage](#advanced-usage)
2527
- [Special variables](#special-variables)
28+
- [Advanced Template Features (Helpers)](#advanced-template-features-helpers)
29+
- [Compare Helper](#compare-helper)
30+
- [Condition Helper](#condition-helper)
31+
- [Math Helper](#math-helper)
32+
- [Case Helper](#case-helper)
33+
- [Repeat Helper](#repeat-helper)
34+
- [DateTime Helper](#datetime-helper)
2635
- [Default Templates](#default-templates)
36+
- [Global Default Templates](#global-default-templates)
37+
- [Notebook-Specific Default Templates](#notebook-specific-default-templates)
2738
- [Using notebooks to store templates](#using-notebooks-to-store-templates)
2839
- [Changelog](#changelog)
2940
- [Supporting](#supporting)
@@ -142,20 +153,22 @@ These are the variables that have a specific purpose other than being used in te
142153
- Both built-in and custom variables can be used while defining these variables.
143154
- The values of these variables can be used in the template body just like built-in and custom variables.
144155

145-
Currently there are two special variables.
156+
Currently there are four special variables.
146157

147158
| Variable | Purpose | Example |
148159
| --- | --- | --- |
149160
| `template_title` | Title of the note/to-do created using this template. | template_title: Standup - {{ date }} |
150161
| `template_tags` | Comma separated tags to be applied to the note/to-do created using this template. | template_tags: spec, {{ project }} |
151162
| `template_notebook` | The ID of the target notebook for this template. Whenever a new note/to-do will be created by this template, it will be created in this target notebook. | template_notebook: 82d2384b025f44588e4d3851a1237028 |
163+
| `template_todo_alarm` | The date and time for a to-do alarm/reminder. Only applies when creating to-dos from templates. | template_todo_alarm: {{ datetime delta_days=1 format="YYYY-MM-DD HH:mm" }} |
152164

153165
**Points to note**
154166
- If `template_title` is not provided, the title of the template will be used as a fallback value.
155167
- If a tag specified in `template_tags` doesn't exist already, it will be created.
156-
- You can't use these variable names i.e. `template_title` and `template_tags` for custom variables. In general, please avoid defining custom variables with `template_` prefix.
168+
- You can't use these variable names i.e. `template_title`, `template_tags`, `template_notebook`, and `template_todo_alarm` for custom variables. In general, please avoid defining custom variables with `template_` prefix.
157169
- To get the ID of a notebook, you can right click on that notebook and click on `Copy notebook ID`.
158170
- While you are inserting the template in an existing note/to-do, `template_tags` variable is used to apply those tags to the note the template is inserted in. However, you can disable using `template_tags` while inserting templates from the plugin settings.
171+
- The `template_todo_alarm` variable expects a date-time string in the format "YYYY-MM-DD HH:mm" (without seconds). You can use the `datetime` helper to generate properly formatted timestamps.
159172

160173
**Example of a template using special variables**
161174

@@ -172,8 +185,304 @@ template_tags: meeting notes, {{ project }}
172185
This note contains the meeting minutes of the weekly meet held on {{ datetime }} for {{ project }}.
173186
```
174187

188+
## Advanced Template Features (Helpers)
189+
190+
The plugin uses [Handlebars.js](https://handlebarsjs.com/) as its templating engine, which provides powerful helpers for advanced template logic. These helpers allow you to perform comparisons, mathematical operations, text transformations, loops, and complex date/time manipulations.
191+
192+
> **💡 Tip:** See the [Complete Feature Demonstration Template](DEMO_TEMPLATE.md) for a comprehensive example using all helpers together in a real-world scenario.
193+
194+
### Compare Helper
195+
196+
The `compare` helper allows you to compare two values using various operators. This is useful for conditional logic in your templates.
197+
198+
**Syntax**: `{{#if (compare value1 operator value2)}}...{{/if}}`
199+
200+
**Supported operators**:
201+
| Operator | Alternative Names | Description |
202+
| --- | --- | --- |
203+
| `==` | `eq`, `equals` | Equal (type coercion) |
204+
| `===` | `seq`, `strictly-equals` | Strictly equal (no type coercion) |
205+
| `!=` | `ne`, `not-equals` | Not equal |
206+
| `!==` | `sne`, `strictly-not-equals` | Strictly not equal |
207+
| `<` | `lt`, `less-than` | Less than |
208+
| `<=` | `lte`, `less-than-equals` | Less than or equal |
209+
| `>` | `gt`, `greater-than` | Greater than |
210+
| `>=` | `gte`, `greater-than-equals` | Greater than or equal |
211+
212+
**Example**:
213+
```markdown
214+
---
215+
age: number
216+
temperature: number
217+
218+
---
219+
220+
{{#if (compare age ">" 18)}}
221+
You are an adult.
222+
{{else}}
223+
You are a minor.
224+
{{/if}}
225+
226+
{{#if (compare temperature ">=" 30)}}
227+
It's hot outside! 🌞
228+
{{else if (compare temperature "<" 10)}}
229+
It's cold outside! ❄️
230+
{{else}}
231+
The weather is pleasant.
232+
{{/if}}
233+
```
234+
235+
### Condition Helper
236+
237+
The `condition` helper provides logical operators for combining multiple conditions.
238+
239+
**Syntax**: `{{#if (condition value1 operator value2)}}...{{/if}}`
240+
241+
**Supported operators**:
242+
| Operator | Alternative Names | Description |
243+
| --- | --- | --- |
244+
| `&&` | `and` | Logical AND |
245+
| `\|\|` | `or` | Logical OR |
246+
247+
**Example**:
248+
```markdown
249+
---
250+
show_summary: boolean
251+
has_data: boolean
252+
is_weekend: boolean
253+
254+
---
255+
256+
{{#if (condition show_summary "and" has_data)}}
257+
## Summary
258+
Data is available and summary display is enabled.
259+
{{/if}}
260+
261+
{{#if (condition is_weekend "or" (compare temperature ">" 25))}}
262+
Perfect day for outdoor activities!
263+
{{/if}}
264+
265+
{{! For negation, use Handlebars' built-in unless helper }}
266+
{{#unless show_summary}}
267+
Summary is hidden.
268+
{{/unless}}
269+
```
270+
271+
**Note**: For simple boolean negation, use Handlebars' built-in `{{#unless variable}}` helper instead of the condition helper.
272+
273+
### Math Helper
274+
275+
The `math` helper performs mathematical operations on numbers.
276+
277+
**Syntax**: `{{math value1 operator value2}}`
278+
279+
**Supported operators**:
280+
| Operator | Description |
281+
| --- | --- |
282+
| `+` | Addition |
283+
| `-` | Subtraction |
284+
| `*` | Multiplication |
285+
| `/` | Division |
286+
| `**` | Exponentiation (power) |
287+
| `%` | Modulo (remainder) |
288+
289+
**Example**:
290+
```markdown
291+
---
292+
price: number
293+
quantity: number
294+
tax_rate: number
295+
296+
---
297+
298+
# Invoice
299+
300+
Price per item: ${{price}}
301+
Quantity: {{quantity}}
302+
Subtotal: ${{math price "*" quantity}}
303+
Tax ({{math tax_rate "*" 100}}%): ${{math (math price "*" quantity) "*" tax_rate}}
304+
**Total: ${{math (math price "*" quantity) "*" (math 1 "+" tax_rate)}}**
305+
306+
---
307+
308+
Area of circle with radius 5: {{math (math 5 "**" 2) "*" 3.14159}}
309+
```
310+
311+
### Case Helper
312+
313+
The `case` helper transforms text to different cases.
314+
315+
**Syntax**: `{{case type text}}`
316+
317+
**Supported types**:
318+
| Type | Description |
319+
| --- | --- |
320+
| `upper` | Convert to UPPERCASE |
321+
| `lower` | Convert to lowercase |
322+
323+
**Example**:
324+
```markdown
325+
---
326+
name: text
327+
company: text
328+
329+
---
330+
331+
# Welcome {{case "upper" name}}!
332+
333+
Company: {{case "upper" company}}
334+
Email: {{case "lower" name}}@{{case "lower" company}}.com
335+
```
336+
337+
### Repeat Helper
338+
339+
The `repeat` helper repeats a block of content a specified number of times. Inside the block, you have access to a `repeat_index` variable (0-based).
340+
341+
**Syntax**: `{{#repeat count}}...{{/repeat}}`
342+
343+
**Example**:
344+
```markdown
345+
---
346+
num_items: number
347+
348+
---
349+
350+
# Checklist
351+
352+
{{#repeat num_items}}
353+
- [ ] Item {{math repeat_index "+" 1}}:
354+
{{/repeat}}
355+
356+
---
357+
358+
# Weekly Goals
359+
360+
{{#repeat 7}}
361+
## Day {{math repeat_index "+" 1}}
362+
- Morning:
363+
- Afternoon:
364+
- Evening:
365+
366+
{{/repeat}}
367+
```
368+
369+
### DateTime Helper
370+
371+
The `datetime` helper provides advanced date and time manipulation capabilities. It allows you to set specific dates/times, add/subtract time intervals, and format the output.
372+
373+
**Syntax**: `{{datetime attribute1=value1 attribute2=value2 ...}}`
374+
375+
**Supported attributes**:
376+
| Attribute | Type | Description | Example |
377+
| --- | --- | --- | --- |
378+
| `format` | string | Output format (moment.js format) | `"YYYY-MM-DD"` |
379+
| `set_date` | string | Set a specific date | `"2024-12-31"` |
380+
| `set_time` | string | Set a specific time | `"09:00:00"` |
381+
| `delta_years` | number | Add/subtract years | `1` or `-1` |
382+
| `delta_months` | number | Add/subtract months | `3` or `-2` |
383+
| `delta_days` | number | Add/subtract days | `7` or `-14` |
384+
| `delta_hours` | number | Add/subtract hours | `2` or `-3` |
385+
| `delta_minutes` | number | Add/subtract minutes | `30` or `-15` |
386+
| `delta_seconds` | number | Add/subtract seconds | `45` or `-10` |
387+
388+
**Examples**:
389+
```markdown
390+
# Date Manipulation Examples
391+
392+
Today: {{datetime}}
393+
Tomorrow: {{datetime delta_days=1}}
394+
Next week: {{datetime delta_days=7}}
395+
One month from now: {{datetime delta_months=1}}
396+
Last year: {{datetime delta_years=-1}}
397+
398+
# Specific Date/Time
399+
New Year: {{datetime set_date="2024-01-01" set_time="00:00:00"}}
400+
Project deadline: {{datetime set_date="2024-12-31" set_time="23:59:59"}}
401+
402+
# Custom Formatting
403+
ISO format: {{datetime format="YYYY-MM-DD HH:mm:ss"}}
404+
Readable: {{datetime format="MMMM Do, YYYY [at] h:mm A"}}
405+
Short: {{datetime format="MM/DD/YY"}}
406+
407+
# Combined Operations
408+
Meeting in 2 days at 2 PM: {{datetime delta_days=2 set_time="14:00" format="YYYY-MM-DD HH:mm"}}
409+
```
410+
411+
**Using with template_todo_alarm**:
412+
```markdown
413+
---
414+
days_until_due: number
415+
template_title: Task due in {{days_until_due}} days
416+
template_todo_alarm: {{datetime delta_days=days_until_due set_time="09:00" format="YYYY-MM-DD HH:mm"}}
417+
418+
---
419+
420+
This task is due on {{datetime delta_days=days_until_due format="MMMM Do, YYYY"}}.
421+
```
422+
423+
**Points to note**:
424+
- All date/time operations start from the current date and time
425+
- When using `set_date`, the format should match your Joplin date format settings (found in Preferences > General)
426+
- When using `set_time`, the format should match your Joplin time format settings (typically "HH:mm" for 24-hour or "h:mm A" for 12-hour format, without seconds)
427+
- Delta operations are applied after any set operations
428+
- The default output format matches your Joplin date/time format settings
429+
- For more format options, see [moment.js format documentation](https://momentjs.com/docs/#/displaying/format/)
430+
431+
175432
## Default Templates
176-
You can define the templates you use the most as default templates. Currently you can have two default templates. One for `notes` and one for `to-dos`. You can also assign keyboard shortcuts to these defaults, so that you can quickly create a new note/to-do with the respective default template.
433+
434+
You can define templates you use frequently as default templates, allowing you to quickly create notes and to-dos without selecting a template each time. The plugin supports both global default templates and notebook-specific default templates.
435+
436+
### Global Default Templates
437+
438+
Global default templates apply across all notebooks unless overridden by notebook-specific defaults.
439+
440+
**Setting global defaults:**
441+
1. Go to `Tools` > `Templates` > `Default templates` > `Set default template`
442+
2. Select your desired template
443+
3. Choose the type:
444+
- **Note**: Sets the default for notes only
445+
- **To-do**: Sets the default for to-dos only
446+
- **Both**: Sets the same template as default for both notes and to-dos
447+
448+
**Using global defaults:**
449+
- Use the command "Create note from default template" (`Alt+Shift+N` by default)
450+
- Use the command "Create to-do from default template" (`Alt+Shift+T` by default)
451+
452+
You can customize these keyboard shortcuts in Joplin's keyboard shortcut settings.
453+
454+
### Notebook-Specific Default Templates
455+
456+
Notebook-specific default templates allow you to set different default templates for different notebooks. These take precedence over global defaults when you're working in a specific notebook.
457+
458+
**Setting notebook-specific defaults:**
459+
1. Go to `Tools` > `Templates` > `Default templates` > `Set default template for notebook`
460+
2. Select the target notebook
461+
3. Select your desired template
462+
4. Choose the type (Note, To-do, or Both)
463+
464+
**Example use cases:**
465+
- **Work notebook**: Use a professional meeting notes template by default
466+
- **Personal notebook**: Use a daily journal template by default
467+
- **Projects notebook**: Use a project task template by default
468+
469+
**Viewing all default templates:**
470+
Go to `Tools` > `Templates` > `Default templates` > `Show default templates` to see:
471+
- Your global default templates (for notes and to-dos)
472+
- All notebook-specific default templates
473+
474+
**Clearing notebook-specific defaults:**
475+
If you want to remove the default templates for a specific notebook (reverting to global defaults):
476+
1. Go to `Tools` > `Templates` > `Default templates` > `Clear default templates for notebook`
477+
2. Select the notebook
478+
3. Confirm the action
479+
480+
**Precedence rules:**
481+
When you create a note/to-do from the default template:
482+
1. If the current notebook has a specific default template → use it
483+
2. Otherwise → use the global default template
484+
3. If no default is set → show an error message
485+
177486

178487
## Using notebooks to store templates
179488
The plugin also supports using notebooks to store templates instead of tags. You can start using notebooks to store your templates by going to the plugin settings and selecting `Notebook` instead of `Tag`.

src/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ joplin.plugins.register({
4747

4848
// Asynchronously load legacy templates
4949
const version = await joplin.versionInfo();
50-
if (version.platform === 'desktop') {
50+
if (version.platform === "desktop") {
5151
loadLegacyTemplates(dateAndTimeUtils, profileDir);
5252
} else {
53-
logger.log('Legacy templates loading skipped on mobile');
53+
logger.log("Legacy templates loading skipped on mobile");
5454
}
5555

5656

@@ -246,7 +246,7 @@ joplin.plugins.register({
246246
name: "showPluginDocumentation",
247247
label: "Help",
248248
execute: async () => {
249-
await joplin.commands.execute('openItem', DOCUMENTATION_URL);
249+
await joplin.commands.execute("openItem", DOCUMENTATION_URL);
250250
}
251251
}));
252252

@@ -314,7 +314,7 @@ joplin.plugins.register({
314314
// Folder context menu
315315
await joplin.views.menuItems.create("templates_folderid", "copyFolderID", MenuItemLocation.FolderContextMenu);
316316

317-
if (version.platform === 'mobile') {
317+
if (version.platform === "mobile") {
318318
const commandsPanel = new CommandsPanel([
319319
{
320320
label: "Create note from template",

src/logger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export class Logger {
1515
}
1616

1717
public async log(message: string): Promise<void> {
18-
if (this.platform === 'desktop') {
18+
if (this.platform === "desktop") {
1919
const fs = joplin.require("fs-extra");
2020
await fs.appendFile(this.logsFile, `[${new Date().toISOString()}]\n${message}\n\n\n`);
2121
} else {

0 commit comments

Comments
 (0)