@hyperbook/markdown 0.22.0 → 0.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,33 +1,61 @@
1
1
  var hyperbook = (function () {
2
- const collapsibles = document.getElementsByClassName("collapsible");
2
+ /**
3
+ * Initialize elements within the given root element.
4
+ * @param {HTMLElement} root - The root element to initialize.
5
+ */
6
+ const init = (root) => {
7
+ const collapsibles = root.getElementsByClassName("collapsible");
8
+ for (let collapsible of collapsibles) {
9
+ collapsible.addEventListener("click", () => {
10
+ const id = collapsible.parentElement.getAttribute("data-id");
11
+ collapsible.classList.toggle("expanded");
12
+ const expanded = collapsible.classList.contains("expanded");
13
+ if (id) {
14
+ [...collapsibles]
15
+ .filter((c) => c.parentElement.getAttribute("data-id") === id)
16
+ .forEach((c) => {
17
+ if (expanded) {
18
+ c.classList.add("expanded");
19
+ } else {
20
+ c.classList.remove("expanded");
21
+ }
22
+ });
23
+ }
24
+ });
25
+ }
3
26
 
4
- for (let collapsible of collapsibles) {
5
- collapsible.addEventListener("click", () => {
6
- collapsible.classList.toggle("expanded");
7
- });
8
- }
27
+ const searchInputEl = root.querySelector("#search-input");
28
+ if (searchInputEl) {
29
+ searchInputEl.addEventListener("keypress", (event) => {
30
+ if (event.key === "Enter") {
31
+ event.preventDefault();
32
+ search();
33
+ }
34
+ });
35
+ }
9
36
 
37
+ initBookmarks(root);
38
+ };
39
+
40
+ /**
41
+ * Toggle the table of contents drawer.
42
+ */
10
43
  function tocToggle() {
11
44
  const tocDrawerEl = document.getElementById("toc-drawer");
12
45
  tocDrawerEl.open = !tocDrawerEl.open;
13
46
  }
14
- // search
15
-
16
- const searchInputEl = document.getElementById("search-input");
17
- if (searchInputEl) {
18
- searchInputEl.addEventListener("keypress", (event) => {
19
- if (event.key === "Enter") {
20
- event.preventDefault();
21
- search();
22
- }
23
- });
24
- }
25
47
 
48
+ /**
49
+ * Toggle the search drawer.
50
+ */
26
51
  function searchToggle() {
27
52
  const searchDrawerEl = document.getElementById("search-drawer");
28
53
  searchDrawerEl.open = !searchDrawerEl.open;
29
54
  }
30
55
 
56
+ /**
57
+ * Perform a search and display the results.
58
+ */
31
59
  function search() {
32
60
  const resultsEl = document.getElementById("search-results");
33
61
  resultsEl.innerHTML = "";
@@ -83,6 +111,9 @@ var hyperbook = (function () {
83
111
  }
84
112
  }
85
113
 
114
+ /**
115
+ * Open the QR code dialog.
116
+ */
86
117
  function qrcodeOpen() {
87
118
  const qrCodeDialog = document.getElementById("qrcode-dialog");
88
119
  const qrcodeEls = qrCodeDialog.getElementsByClassName("make-qrcode");
@@ -106,19 +137,26 @@ var hyperbook = (function () {
106
137
  qrCodeDialog.showModal();
107
138
  }
108
139
 
140
+ /**
141
+ * Close the QR code dialog.
142
+ */
109
143
  function qrcodeClose() {
110
144
  const qrCodeDialog = document.getElementById("qrcode-dialog");
111
145
  qrCodeDialog.close();
112
146
  }
113
147
 
148
+ /**
149
+ * Toggle the navigation drawer.
150
+ */
114
151
  function navToggle() {
115
152
  const navDrawerEl = document.getElementById("nav-drawer");
116
153
  navDrawerEl.open = !navDrawerEl.open;
117
154
  }
118
155
 
119
156
  /**
120
- * @param {string} key
121
- * @param {string} label
157
+ * Toggle a bookmark.
158
+ * @param {string} key - The key of the bookmark.
159
+ * @param {string} label - The label of the bookmark.
122
160
  */
123
161
  function toggleBookmark(key, label) {
124
162
  const bookmarks = JSON.parse(localStorage.getItem("bookmarks") || "{}");
@@ -137,8 +175,12 @@ var hyperbook = (function () {
137
175
  }
138
176
  }
139
177
 
140
- function initBookmarks() {
141
- const bookmarkEls = document.getElementsByClassName("bookmark");
178
+ /**
179
+ * Initialize bookmarks within the given root element.
180
+ * @param {HTMLElement} [root=document] - The root element to initialize.
181
+ */
182
+ function initBookmarks(root = document) {
183
+ const bookmarkEls = root.getElementsByClassName("bookmark");
142
184
  const bookmarks = JSON.parse(localStorage.getItem("bookmarks") || "{}");
143
185
  for (let bookmarkEl of bookmarkEls) {
144
186
  const key = bookmarkEl.getAttribute("data-key");
@@ -147,15 +189,35 @@ var hyperbook = (function () {
147
189
  }
148
190
  }
149
191
  }
150
- initBookmarks();
151
192
 
152
193
  /**
153
- * @param {HTMLElement} el
194
+ * Toggle the lightbox view of an element.
195
+ * @param {HTMLElement} el - The element to toggle.
154
196
  */
155
197
  function toggleLightbox(el) {
156
198
  el.parentElement.classList.toggle("lightbox");
157
199
  el.parentElement.classList.toggle("normal");
158
200
  }
201
+
202
+ // Initialize existing elements on document load
203
+ document.addEventListener("DOMContentLoaded", () => {
204
+ init(document);
205
+ });
206
+
207
+ // Observe for new elements added to the DOM
208
+ const observer = new MutationObserver((mutations) => {
209
+ mutations.forEach((mutation) => {
210
+ mutation.addedNodes.forEach((node) => {
211
+ if (node.nodeType === 1) {
212
+ // Element node
213
+ init(node);
214
+ }
215
+ });
216
+ });
217
+ });
218
+
219
+ observer.observe(document.body, { childList: true, subtree: true });
220
+
159
221
  return {
160
222
  toggleLightbox,
161
223
  toggleBookmark,
@@ -165,5 +227,6 @@ var hyperbook = (function () {
165
227
  search,
166
228
  qrcodeOpen,
167
229
  qrcodeClose,
230
+ init,
168
231
  };
169
232
  })();
@@ -1,5 +1,4 @@
1
1
  hyperbook.abc = (function () {
2
- const els = document.querySelectorAll(".directive-abc-music");
3
2
  window.codeInput?.registerTemplate(
4
3
  "abc-highlighted",
5
4
  codeInput.templates.prism(window.Prism, [
@@ -7,7 +6,7 @@ hyperbook.abc = (function () {
7
6
  ])
8
7
  );
9
8
 
10
- for (let el of els) {
9
+ const initABC = (el) => {
11
10
  const tuneEl = el.getElementsByClassName("tune")[0];
12
11
  const playerEl = el.getElementsByClassName("player")[0];
13
12
 
@@ -60,5 +59,32 @@ hyperbook.abc = (function () {
60
59
  "<div class='audio-error'>Audio is not supported in this browser.</div>";
61
60
  }
62
61
  }
63
- }
64
- })();
62
+ };
63
+
64
+ const init = (root) => {
65
+ const els = root.querySelectorAll(".directive-abc-music");
66
+ els.forEach(initABC);
67
+ };
68
+
69
+ // Initialize existing elements on document load
70
+ document.addEventListener("DOMContentLoaded", () => {
71
+ init(document);
72
+ });
73
+
74
+ // Observe for new elements added to the DOM
75
+ const observer = new MutationObserver((mutations) => {
76
+ mutations.forEach((mutation) => {
77
+ mutation.addedNodes.forEach((node) => {
78
+ if (node.nodeType === 1 && node.classList.contains("directive-abc-music")) {
79
+ initABC(node);
80
+ }
81
+ });
82
+ });
83
+ });
84
+
85
+ observer.observe(document.body, { childList: true, subtree: true });
86
+
87
+ return {
88
+ init,
89
+ };
90
+ })();
@@ -1,23 +1,40 @@
1
1
  hyperbook.download = (function () {
2
+ function initElement(el) {
3
+ const labelEl = el.getElementsByClassName("label")[0];
4
+ const src = el.href;
5
+
6
+ fetch(src).then((r) => {
7
+ const isOnline = r.ok;
8
+ if (isOnline) {
9
+ labelEl.classList.remove("offline");
10
+ labelEl.innerHTML = labelEl.innerHTML.replace("(Offline)", "");
11
+ } else {
12
+ labelEl.classList.add("offline");
13
+ labelEl.innerHTML += " (Offline)";
14
+ }
15
+ });
16
+ }
17
+
2
18
  function init() {
3
19
  const els = document.getElementsByClassName("directive-archive");
4
20
  for (let el of els) {
5
- const labelEl = el.getElementsByClassName("label")[0];
6
-
7
- const src = el.href;
21
+ initElement(el);
22
+ }
23
+ }
8
24
 
9
- fetch(src).then((r) => {
10
- const isOnline = r.ok;
11
- if (isOnline) {
12
- labelEl.classList.remove("offline");
13
- labelEl.innerHTML.replace("(Offline)", "");
14
- } else {
15
- labelEl.classList.add("offline");
16
- labelEl.innerHTML += " (Offline)";
25
+ const observer = new MutationObserver((mutations) => {
26
+ for (let mutation of mutations) {
27
+ if (mutation.type === "childList") {
28
+ for (let node of mutation.addedNodes) {
29
+ if (node.classList && node.classList.contains("directive-archive")) {
30
+ initElement(node);
31
+ }
17
32
  }
18
- });
33
+ }
19
34
  }
20
- }
35
+ });
36
+
37
+ observer.observe(document.body, { childList: true, subtree: true });
21
38
 
22
39
  init();
23
40
  })();
@@ -1,13 +1,13 @@
1
1
  hyperbook.bookmarks = (function () {
2
- function update() {
2
+ function update(root = document) {
3
3
  const bookmarks = JSON.parse(localStorage.getItem("bookmarks") || "{}");
4
4
 
5
- const containerEls = document.getElementsByClassName("directive-bookmarks");
5
+ const containerEls = root.getElementsByClassName("directive-bookmarks");
6
6
  for (let containerEl of containerEls) {
7
7
  const elements = [];
8
8
  Object.entries(bookmarks).forEach(([key, label]) => {
9
- const bookmarkEl = document.createElement("li");
10
- const link = document.createElement("a");
9
+ const bookmarkEl = root.createElement("li");
10
+ const link = root.createElement("a");
11
11
  link.href = key;
12
12
  link.innerHTML = label;
13
13
  bookmarkEl.append(link);
@@ -16,7 +16,24 @@ hyperbook.bookmarks = (function () {
16
16
  containerEl.replaceChildren(...elements);
17
17
  }
18
18
  }
19
- update();
19
+
20
+ // Initialize existing elements on document load
21
+ document.addEventListener("DOMContentLoaded", () => {
22
+ update(document);
23
+ });
24
+
25
+ // Observe for new elements added to the DOM
26
+ const observer = new MutationObserver((mutations) => {
27
+ mutations.forEach((mutation) => {
28
+ mutation.addedNodes.forEach((node) => {
29
+ if (node.nodeType === 1 && node.classList.contains("directive-bookmarks")) { // Element node
30
+ update(node);
31
+ }
32
+ });
33
+ });
34
+ });
35
+
36
+ observer.observe(document.body, { childList: true, subtree: true });
20
37
 
21
38
  return {
22
39
  update,
@@ -1,6 +1,6 @@
1
1
  hyperbook.download = (function () {
2
- function init() {
3
- const els = document.getElementsByClassName("directive-download");
2
+ const init = (root) => {
3
+ const els = root.getElementsByClassName("directive-download");
4
4
  for (let el of els) {
5
5
  const labelEl = el.getElementsByClassName("label")[0];
6
6
 
@@ -17,7 +17,27 @@ hyperbook.download = (function () {
17
17
  }
18
18
  });
19
19
  }
20
- }
20
+ };
21
21
 
22
- init();
22
+ // Initialize existing elements on document load
23
+ document.addEventListener("DOMContentLoaded", () => {
24
+ init(document);
25
+ });
26
+
27
+ // Observe for new elements added to the DOM
28
+ const observer = new MutationObserver((mutations) => {
29
+ mutations.forEach((mutation) => {
30
+ mutation.addedNodes.forEach((node) => {
31
+ if (node.nodeType === 1) { // Element node
32
+ init(node);
33
+ }
34
+ });
35
+ });
36
+ });
37
+
38
+ observer.observe(document.body, { childList: true, subtree: true });
39
+
40
+ return {
41
+ init,
42
+ };
23
43
  })();
@@ -1,9 +1,11 @@
1
1
  hyperbook.mermaid = (function () {
2
2
  const elementCode = ".directive-mermaid";
3
+
3
4
  const loadMermaid = function (theme) {
4
5
  window.mermaid.initialize({ theme });
5
6
  window.mermaid.init({ theme }, document.querySelectorAll(elementCode));
6
7
  };
8
+
7
9
  const resetProcessed = function () {
8
10
  return new Promise((resolve, reject) => {
9
11
  try {
@@ -35,19 +37,54 @@ hyperbook.mermaid = (function () {
35
37
  const init = () => {
36
38
  const toggle = document.querySelector("dark-mode-toggle");
37
39
  if (toggle?.mode == "dark") {
38
- resetProcessed().then(loadMermaid("dark")).catch(console.error);
40
+ resetProcessed()
41
+ .then(() => loadMermaid("dark"))
42
+ .catch(console.error);
39
43
  } else {
40
- resetProcessed().then(loadMermaid("default")).catch(console.error);
44
+ resetProcessed()
45
+ .then(() => loadMermaid("default"))
46
+ .catch(console.error);
41
47
  }
42
48
 
43
49
  document.addEventListener("colorschemechange", (e) => {
44
50
  if (e.detail.colorScheme === "dark") {
45
- resetProcessed().then(loadMermaid("dark")).catch(console.error);
51
+ resetProcessed()
52
+ .then(() => loadMermaid("dark"))
53
+ .catch(console.error);
46
54
  } else {
47
- resetProcessed().then(loadMermaid("default")).catch(console.error);
55
+ resetProcessed()
56
+ .then(() => loadMermaid("default"))
57
+ .catch(console.error);
48
58
  }
49
59
  });
50
60
  };
51
61
 
52
62
  init();
63
+
64
+ // Observe for new elements added to the DOM
65
+ const observer = new MutationObserver((mutations) => {
66
+ mutations.forEach((mutation) => {
67
+ mutation.addedNodes.forEach((node) => {
68
+ if (node.nodeType === 1 && node.hasAttribute("data-mermaid")) {
69
+ // Element node
70
+ const toggle = document.querySelector("dark-mode-toggle");
71
+ if (toggle?.mode == "dark") {
72
+ resetProcessed()
73
+ .then(() => loadMermaid("dark"))
74
+ .catch(console.error);
75
+ } else {
76
+ resetProcessed()
77
+ .then(() => loadMermaid("default"))
78
+ .catch(console.error);
79
+ }
80
+ }
81
+ });
82
+ });
83
+ });
84
+
85
+ observer.observe(document.body, { childList: true, subtree: true });
86
+
87
+ return {
88
+ init,
89
+ };
53
90
  })();
@@ -56,8 +56,12 @@ hyperbook.protect = (function () {
56
56
  localStorage.setItem("protect", JSON.stringify(protect));
57
57
  }
58
58
 
59
- function init() {
60
- const els = document.getElementsByClassName("directive-protect");
59
+ /**
60
+ * Initialize elements within the given root element.
61
+ * @param {HTMLElement} root - The root element to initialize.
62
+ */
63
+ function init(root) {
64
+ const els = root.getElementsByClassName("directive-protect");
61
65
  for (let el of els) {
62
66
  const inputEl = el.getElementsByTagName("input")[0];
63
67
 
@@ -75,5 +79,25 @@ hyperbook.protect = (function () {
75
79
  }
76
80
  }
77
81
 
78
- init();
82
+ // Initialize existing elements on document load
83
+ document.addEventListener("DOMContentLoaded", () => {
84
+ init(document);
85
+ });
86
+
87
+ // Observe for new elements added to the DOM
88
+ const observer = new MutationObserver((mutations) => {
89
+ mutations.forEach((mutation) => {
90
+ mutation.addedNodes.forEach((node) => {
91
+ if (node.nodeType === 1) { // Element node
92
+ init(node);
93
+ }
94
+ });
95
+ });
96
+ });
97
+
98
+ observer.observe(document.body, { childList: true, subtree: true });
99
+
100
+ return {
101
+ init,
102
+ };
79
103
  })();
@@ -65,6 +65,7 @@ hyperbook.python = (function () {
65
65
  }
66
66
 
67
67
  const updateRunning = (id, type) => {
68
+ const elems = document.getElementsByClassName("directive-pyide");
68
69
  for (let elem of elems) {
69
70
  const run = elem.getElementsByClassName("run")[0];
70
71
  const test = elem.getElementsByClassName("test")[0];
@@ -121,55 +122,83 @@ hyperbook.python = (function () {
121
122
  }
122
123
  };
123
124
 
124
- const elems = document.getElementsByClassName("directive-pyide");
125
-
126
- for (let elem of elems) {
127
- const editor = elem.getElementsByClassName("editor")[0];
128
- const run = elem.getElementsByClassName("run")[0];
129
- const test = elem.getElementsByClassName("test")[0];
130
- const output = elem.getElementsByClassName("output")[0];
131
- const input = elem.getElementsByClassName("input")[0];
132
- const outputBtn = elem.getElementsByClassName("output-btn")[0];
133
- const inputBtn = elem.getElementsByClassName("input-btn")[0];
134
- const id = elem.id;
135
- let tests = [];
136
- try {
137
- tests = JSON.parse(atob(elem.getAttribute("data-tests")));
138
- } catch (e) {}
139
-
140
- function showInput() {
141
- outputBtn.classList.remove("active");
142
- inputBtn.classList.add("active");
143
- output.classList.add("hidden");
144
- input.classList.remove("hidden");
145
- }
146
- function showOutput() {
147
- outputBtn.classList.add("active");
148
- inputBtn.classList.remove("active");
149
- output.classList.remove("hidden");
150
- input.classList.add("hidden");
151
- }
152
-
153
- outputBtn?.addEventListener("click", showOutput);
154
- inputBtn?.addEventListener("click", showInput);
125
+ const init = (root) => {
126
+ const elems = root.getElementsByClassName("directive-pyide");
155
127
 
156
- test?.addEventListener("click", async () => {
157
- showOutput();
158
- if (callback) return;
159
-
160
- output.innerHTML = "";
128
+ for (let elem of elems) {
129
+ const editor = elem.getElementsByClassName("editor")[0];
130
+ const run = elem.getElementsByClassName("run")[0];
131
+ const test = elem.getElementsByClassName("test")[0];
132
+ const output = elem.getElementsByClassName("output")[0];
133
+ const input = elem.getElementsByClassName("input")[0];
134
+ const outputBtn = elem.getElementsByClassName("output-btn")[0];
135
+ const inputBtn = elem.getElementsByClassName("input-btn")[0];
136
+ const id = elem.id;
137
+ let tests = [];
138
+ try {
139
+ tests = JSON.parse(atob(elem.getAttribute("data-tests")));
140
+ } catch (e) {}
141
+
142
+ function showInput() {
143
+ outputBtn.classList.remove("active");
144
+ inputBtn.classList.add("active");
145
+ output.classList.add("hidden");
146
+ input.classList.remove("hidden");
147
+ }
148
+ function showOutput() {
149
+ outputBtn.classList.add("active");
150
+ inputBtn.classList.remove("active");
151
+ output.classList.remove("hidden");
152
+ input.classList.add("hidden");
153
+ }
161
154
 
162
- const script = editor.value;
163
- for (let test of tests) {
164
- const testCode = test.code.replace("#SCRIPT#", script);
155
+ outputBtn?.addEventListener("click", showOutput);
156
+ inputBtn?.addEventListener("click", showInput);
157
+
158
+ test?.addEventListener("click", async () => {
159
+ showOutput();
160
+ if (callback) return;
161
+
162
+ output.innerHTML = "";
163
+
164
+ const script = editor.value;
165
+ for (let test of tests) {
166
+ const testCode = test.code.replace("#SCRIPT#", script);
167
+
168
+ const heading = document.createElement("div");
169
+ console.log(test);
170
+ heading.innerHTML = `== Test ${test.name} ==`;
171
+ heading.classList.add("test-heading");
172
+ output.appendChild(heading);
173
+
174
+ await asyncRun(id, "test")(testCode, {})
175
+ .then(({ results, error }) => {
176
+ if (results) {
177
+ output.textContent += results;
178
+ } else if (error) {
179
+ output.textContent += error;
180
+ }
181
+ callback = null;
182
+ updateRunning(id, "test");
183
+ })
184
+ .catch((e) => {
185
+ output.textContent = `Error: ${e}`;
186
+ console.log(e);
187
+ callback = null;
188
+ updateRunning(id, "test");
189
+ });
190
+ }
191
+ });
165
192
 
166
- const heading = document.createElement("div");
167
- console.log(test);
168
- heading.innerHTML = `== Test ${test.name} ==`;
169
- heading.classList.add("test-heading");
170
- output.appendChild(heading);
193
+ run?.addEventListener("click", async () => {
194
+ showOutput();
195
+ if (callback) return;
171
196
 
172
- await asyncRun(id, "test")(testCode, {})
197
+ const script = editor.value;
198
+ output.innerHTML = "";
199
+ asyncRun(id, "run")(script, {
200
+ inputs: input.value.split("\n"),
201
+ })
173
202
  .then(({ results, error }) => {
174
203
  if (results) {
175
204
  output.textContent += results;
@@ -177,41 +206,33 @@ hyperbook.python = (function () {
177
206
  output.textContent += error;
178
207
  }
179
208
  callback = null;
180
- updateRunning(id, "test");
209
+ updateRunning(id, "run");
181
210
  })
182
211
  .catch((e) => {
183
212
  output.textContent = `Error: ${e}`;
184
213
  console.log(e);
185
214
  callback = null;
186
- updateRunning(id, "test");
215
+ updateRunning(id, "run");
187
216
  });
188
- }
189
- });
217
+ });
218
+ }
219
+ };
190
220
 
191
- run?.addEventListener("click", async () => {
192
- showOutput();
193
- if (callback) return;
194
-
195
- const script = editor.value;
196
- output.innerHTML = "";
197
- asyncRun(id, "run")(script, {
198
- inputs: input.value.split("\n"),
199
- })
200
- .then(({ results, error }) => {
201
- if (results) {
202
- output.textContent += results;
203
- } else if (error) {
204
- output.textContent += error;
221
+ const observer = new MutationObserver((mutations) => {
222
+ mutations.forEach((mutation) => {
223
+ if (mutation.addedNodes.length) {
224
+ mutation.addedNodes.forEach((node) => {
225
+ if (node.type === 1 && node.classList?.contains("directive-pyide")) {
226
+ init(node);
205
227
  }
206
- callback = null;
207
- updateRunning(id, "run");
208
- })
209
- .catch((e) => {
210
- output.textContent = `Error: ${e}`;
211
- console.log(e);
212
- callback = null;
213
- updateRunning(id, "run");
214
228
  });
229
+ }
215
230
  });
216
- }
231
+ });
232
+
233
+ observer.observe(document.body, { childList: true, subtree: true });
234
+
235
+ document.addEventListener("DOMContentLoaded", () => {
236
+ init(document);
237
+ });
217
238
  })();