Skip to content

Commit

Permalink
Merge pull request #1241 from SilentVoid13/Zachatoo/AddHooksModule
Browse files Browse the repository at this point in the history
Add hooks module
  • Loading branch information
Zachatoo authored Nov 13, 2023
2 parents 4a5d074 + a965718 commit a6791c9
Show file tree
Hide file tree
Showing 18 changed files with 197 additions and 5 deletions.
19 changes: 19 additions & 0 deletions docs/documentation.toml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,25 @@ description = "Retrieves the file's title."
name = "frontmatter"
description = "This modules exposes all the frontmatter variables of a file as variables."



[tp.hooks]
name = "hooks"
description = "This module exposes hooks that allow you to execute code when a Templater event occurs."

[tp.hooks.functions.on_all_templates_executed]
name = "on_all_templates_executed"
description = """Hooks into when all actively running templates have finished executing. Most of the time this will be a single template, unless you are using `tp.file.include` or `tp.file.create_new`.
Multiple invokations of this method will have their callback functions run in parallel."""
definition = "tp.hooks.on_all_templates_executed(callback_function: () => any)"

[[tp.hooks.functions.on_all_templates_executed.args]]
name = "callback_function"
description = "Callback function that will be executed when all actively running templates have finished executing."



[tp.obsidian]
name = "obsidian"
description = "This module exposes all the functions and classes from the obsidian API."
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- [tp.date](./internal-functions/internal-modules/date-module.md)
- [tp.file](./internal-functions/internal-modules/file-module.md)
- [tp.frontmatter](./internal-functions/internal-modules/frontmatter-module.md)
- [tp.hooks](./internal-functions/internal-modules/hooks-module.md)
- [tp.obsidian](./internal-functions/internal-modules/obsidian-module.md)
- [tp.system](./internal-functions/internal-modules/system-module.md)
- [tp.web](./internal-functions/internal-modules/web-module.md)
Expand Down
52 changes: 52 additions & 0 deletions docs/src/internal-functions/internal-modules/hooks-module.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Hooks Module

{{ tp.hooks.description }}

<!-- toc -->

## Documentation

Function documentation is using a specific syntax. More information [here](../../syntax.md#function-documentation-syntax)


{%- for key, fn in tp.hooks.functions %}
### `{{ fn.definition }}`

{{ fn.description }}

{% if fn.args %}
##### Arguments

{% for arg in fn.args %}
- `{{ arg.name }}`: {{ arg.description }}
{% endfor %}
{% endif %}

{% if fn.example %}
##### Example

```
{{ fn.example }}
```
{% endif %}
{%- endfor %}

## Examples

```javascript
// Update frontmatter after template finishes executing
<%*
tp.hooks.on_all_templates_executed(async () => {
const file = tp.file.find_tfile(tp.file.path(true));
await app.fileManager.processFrontMatter(file, (frontmatter) => {
frontmatter["key"] = "value";
});
});
%>
// Run a command from another plugin that modifies the current file, after Templater has updated the file
<%*
tp.hooks.on_all_templates_executed(() => {
app.commands.executeCommandById("obsidian-linter:lint-file");
});
-%>
```
1 change: 1 addition & 0 deletions docs/src/internal-functions/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The different internal variables and functions offered by [Templater](https://gi
- [Date module](./internal-modules/date-module.md): `tp.date`
- [File module](./internal-modules/file-module.md): `tp.file`
- [Frontmatter module](./internal-modules/frontmatter-module.md): `tp.frontmatter`
- [Hooks module](./internal-modules/hooks-module.md): `tp.hooks`
- [Obsidian module](./internal-modules/obsidian-module.md): `tp.obsidian`
- [System module](./internal-modules/system-module.md): `tp.system`
- [Web module](./internal-modules/web-module.md): `tp.web`
Expand Down
45 changes: 41 additions & 4 deletions src/core/Templater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
MarkdownPostProcessorContext,
MarkdownView,
normalizePath,
requireApiVersion,
TAbstractFile,
TFile,
TFolder,
Expand Down Expand Up @@ -42,13 +41,15 @@ export class Templater {
public parser: Parser;
public functions_generator: FunctionsGenerator;
public current_functions_object: Record<string, unknown>;
private templater_task_counter: number;

constructor(private plugin: TemplaterPlugin) {
this.functions_generator = new FunctionsGenerator(this.plugin);
this.parser = new Parser();
}

async setup(): Promise<void> {
this.templater_task_counter = 0;
await this.parser.init();
await this.functions_generator.init();
this.plugin.registerMarkdownPostProcessor((el, ctx) =>
Expand Down Expand Up @@ -94,12 +95,25 @@ export class Templater {
return content;
}

private start_templater_task() {
this.templater_task_counter++;
}

private async end_templater_task() {
this.templater_task_counter--;
if (this.templater_task_counter === 0) {
app.workspace.trigger("templater:all-templates-executed");
await this.functions_generator.teardown();
}
}

async create_new_note_from_template(
template: TFile | string,
folder?: TFolder,
filename?: string,
open_new_note = true
): Promise<TFile | undefined> {
this.start_templater_task();
// TODO: Maybe there is an obsidian API function for that
if (!folder) {
const new_file_location = app.vault.getConfig("newFileLocation");
Expand All @@ -123,11 +137,20 @@ export class Templater {
}

// TODO: Change that, not stable atm
const created_note = await app.fileManager.createNewMarkdownFile(
folder,
filename ?? "Untitled"
const created_note = await errorWrapper(
async () =>
app.fileManager.createNewMarkdownFile(
folder,
filename ?? "Untitled"
),
"Couldn't create markdown file."
);

if (created_note == null) {
await this.end_templater_task();
return;
}

let running_config: RunningConfig;
let output_content: string;
if (template instanceof TFile) {
Expand All @@ -154,6 +177,7 @@ export class Templater {

if (output_content == null) {
await app.vault.delete(created_note);
await this.end_templater_task();
return;
}

Expand Down Expand Up @@ -184,16 +208,19 @@ export class Templater {
});
}

await this.end_templater_task();
return created_note;
}

async append_template_to_active_file(template_file: TFile): Promise<void> {
this.start_templater_task();
const active_view = app.workspace.getActiveViewOfType(MarkdownView);
const active_editor = app.workspace.activeEditor;
if (!active_editor || !active_editor.file || !active_editor.editor) {
log_error(
new TemplaterError("No active editor, can't append templates.")
);
await this.end_templater_task();
return;
}
const running_config = this.create_running_config(
Expand All @@ -207,13 +234,15 @@ export class Templater {
);
// errorWrapper failed
if (output_content == null) {
await this.end_templater_task();
return;
}

const editor = active_editor.editor;
const doc = editor.getDoc();
const oldSelections = doc.listSelections();
doc.replaceSelection(output_content);
await app.vault.modify(active_editor.file, editor.getValue());

app.workspace.trigger("templater:template-appended", {
view: active_view,
Expand All @@ -227,12 +256,14 @@ export class Templater {
active_editor.file,
true
);
await this.end_templater_task();
}

async write_template_to_file(
template_file: TFile,
file: TFile
): Promise<void> {
this.start_templater_task();
const active_editor = app.workspace.activeEditor;
const running_config = this.create_running_config(
template_file,
Expand Down Expand Up @@ -260,6 +291,7 @@ export class Templater {
file,
true
);
await this.end_templater_task();
}

overwrite_active_file_commands(): void {
Expand All @@ -279,6 +311,7 @@ export class Templater {
file: TFile,
active_file = false
): Promise<void> {
this.start_templater_task();
const running_config = this.create_running_config(
file,
file,
Expand All @@ -290,6 +323,7 @@ export class Templater {
);
// errorWrapper failed
if (output_content == null) {
await this.end_templater_task();
return;
}
await app.vault.modify(file, output_content);
Expand All @@ -301,6 +335,7 @@ export class Templater {
file,
true
);
await this.end_templater_task();
}

async process_dynamic_templates(
Expand Down Expand Up @@ -451,6 +486,7 @@ export class Templater {
if (!file) {
continue;
}
this.start_templater_task();
const running_config = this.create_running_config(
file,
file,
Expand All @@ -460,6 +496,7 @@ export class Templater {
async () => this.read_and_parse_template(running_config),
`Startup Template parsing error, aborting.`
);
await this.end_templater_task();
}
}
}
4 changes: 4 additions & 0 deletions src/core/functions/FunctionsGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export class FunctionsGenerator implements IGenerateObject {
await this.internal_functions.init();
}

async teardown(): Promise<void> {
await this.internal_functions.teardown();
}

additional_functions(): Record<string, unknown> {
return {
obsidian: obsidian_module,
Expand Down
8 changes: 8 additions & 0 deletions src/core/functions/internal_functions/InternalFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { InternalModule } from "./InternalModule";
import { InternalModuleDate } from "./date/InternalModuleDate";
import { InternalModuleFile } from "./file/InternalModuleFile";
import { InternalModuleWeb } from "./web/InternalModuleWeb";
import { InternalModuleHooks } from "./hooks/InternalModuleHooks";
import { InternalModuleFrontmatter } from "./frontmatter/InternalModuleFrontmatter";
import { InternalModuleSystem } from "./system/InternalModuleSystem";
import { RunningConfig } from "core/Templater";
Expand All @@ -17,6 +18,7 @@ export class InternalFunctions implements IGenerateObject {
this.modules_array.push(new InternalModuleFile(this.plugin));
this.modules_array.push(new InternalModuleWeb(this.plugin));
this.modules_array.push(new InternalModuleFrontmatter(this.plugin));
this.modules_array.push(new InternalModuleHooks(this.plugin));
this.modules_array.push(new InternalModuleSystem(this.plugin));
this.modules_array.push(new InternalModuleConfig(this.plugin));
}
Expand All @@ -27,6 +29,12 @@ export class InternalFunctions implements IGenerateObject {
}
}

async teardown(): Promise<void> {
for (const mod of this.modules_array) {
await mod.teardown();
}
}

async generate_object(
config: RunningConfig
): Promise<Record<string, unknown>> {
Expand Down
1 change: 1 addition & 0 deletions src/core/functions/internal_functions/InternalModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export abstract class InternalModule implements IGenerateObject {

abstract create_static_templates(): Promise<void>;
abstract create_dynamic_templates(): Promise<void>;
abstract teardown(): Promise<void>;

async init(): Promise<void> {
await this.create_static_templates();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export class InternalModuleConfig extends InternalModule {

async create_dynamic_templates(): Promise<void> {}

async teardown(): Promise<void> {}

async generate_object(
config: RunningConfig
): Promise<Record<string, unknown>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export class InternalModuleDate extends InternalModule {

async create_dynamic_templates(): Promise<void> {}

async teardown(): Promise<void> {}

generate_now(): (
format?: string,
offset?: number | string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export class InternalModuleFile extends InternalModule {
this.dynamic_functions.set("title", this.generate_title());
}

async teardown(): Promise<void> {}

async generate_content(): Promise<string> {
return await app.vault.read(this.config.target_file);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ export class InternalModuleFrontmatter extends InternalModule {
Object.entries(cache?.frontmatter || {})
);
}

async teardown(): Promise<void> {}
}
38 changes: 38 additions & 0 deletions src/core/functions/internal_functions/hooks/InternalModuleHooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { EventRef } from "obsidian";
import { ModuleName } from "editor/TpDocumentation";
import { InternalModule } from "../InternalModule";

export class InternalModuleHooks extends InternalModule {
public name: ModuleName = "hooks";
private event_refs: EventRef[] = [];

async create_static_templates(): Promise<void> {
this.static_functions.set(
"on_all_templates_executed",
this.generate_on_all_templates_executed()
);
}

async create_dynamic_templates(): Promise<void> {}

async teardown(): Promise<void> {
this.event_refs.forEach((eventRef) => {
eventRef.e.offref(eventRef);
});
this.event_refs = [];
}

generate_on_all_templates_executed(): (
callback_function: () => unknown
) => void {
return (callback_function) => {
const event_ref = app.workspace.on(
"templater:all-templates-executed",
() => callback_function()
);
if (event_ref) {
this.event_refs.push(event_ref);
}
};
}
}
Loading

0 comments on commit a6791c9

Please sign in to comment.