1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 | diff --git a/src/hooks.py b/src/hooks.py
index 085eb2e..7700d33 100644
--- a/src/hooks.py
+++ b/src/hooks.py
@@ -1,49 +1,67 @@
from .log import GRAY, warn
+DEFAULT_PRIORITY = 100
+
hooks = {
- "on_build_end" : None,
- "on_build_start" : None,
- "on_config_load" : None,
- "on_file_changed" : None,
- "on_hash_check" : None,
- "on_hash_written" : None,
- "on_highlight_config" : None,
- "on_html_filter" : None,
- "on_jinja_error" : None,
- "on_jinja_template_dir" : None,
- "on_jinja_template_renderer": None,
- "on_math_renderer" : None,
- "on_md_to_html" : None,
- "on_page_read" : None,
- "on_page_rendered" : None,
- "on_page_skip" : None,
- "on_page_written" : None,
- "on_plugins_before_export" : None,
- "on_plugins_loaded" : None,
- "on_reload_error" : None,
- "on_walk_end" : None,
- "on_walk_file" : None,
- "on_walk_start" : None,
- "on_watch_start" : None,
- "on_watch_stop" : None,
+ "on_build_end" : [],
+ "on_build_start" : [],
+ "on_compile_start" : [],
+ "on_config_load" : [],
+ "on_end" : [],
+ "on_file_changed" : [],
+ "on_hash_check" : [],
+ "on_hash_written" : [],
+ "on_highlight_config" : [],
+ "on_html_filter" : [],
+ "on_jinja_error" : [],
+ "on_jinja_template_dir" : [],
+ "on_jinja_template_renderer": [],
+ "on_math_renderer" : [],
+ "on_md_to_html" : [],
+ "on_page_built" : [],
+ "on_page_read" : [],
+ "on_page_rendered" : [],
+ "on_page_skip" : [],
+ "on_page_written" : [],
+ "on_plugin_changed" : [],
+ "on_plugins_before_export" : [],
+ "on_plugins_loaded" : [],
+ "on_reload_error" : [],
+ "on_start" : [],
+ "on_walk_end" : [],
+ "on_walk_file" : [],
+ "on_walk_start" : [],
+ "on_watch_start" : [],
+ "on_watch_stop" : [],
}
-
-def hook(hook_name:str):
- if hook_name in hooks:
- def hook_fn(fn):
- if not hooks.get(hook_name) == None:
- warn(f"Overwriting existing hook '{hook_name}'.")
- hooks[hook_name]=fn
- return fn
- return hook_fn
- else:
- warn(f"Skipping hook `{GRAY(hook_name)}`: hook is not exists")
- return lambda fn:fn
+def hook(hook_name: str, priority: int = DEFAULT_PRIORITY):
+ if hook_name not in hooks:
+ warn(f"Skipping hook `{GRAY(hook_name)}`: hook does not exist")
+ return lambda fn: fn
+
+ def hook_fn(fn):
+ hooks[hook_name].append((priority, fn))
+ hooks[hook_name].sort(key=lambda x: x[0])
+ return fn
+ return hook_fn
def hook_call(hook_name, *args, **kwargs):
- if hook_name not in hooks:
- warn(hook_name)
- func = hooks.get(hook_name)
- if callable(func):
- return func(*args, **kwargs)
+ subscribers = hooks.get(hook_name, [])
+ if not subscribers:
+ return None
+ result = None
+ for _priority, fn in subscribers:
+ try:
+ result = fn(*args, **kwargs)
+ except Exception as e:
+ warn(f"Hook '{hook_name}' failed in {fn.__name__}: {e}")
+ return result
+
+def reset_hooks():
+ for key in hooks:
+ hooks[key] = []
+
+def remove_hook(hook_name, fn):
+ if hook_name in hooks:
+ hooks[hook_name] = [(p, f) for p, f in hooks[hook_name] if f is not fn]
|