ep_table_of_contents 0.3.133 → 0.3.135

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.
package/README.md CHANGED
@@ -5,6 +5,23 @@
5
5
  Enable under settings.
6
6
  Create headings, watch the TOC populate in real time.
7
7
 
8
+ ## Installation
9
+
10
+ Install the way Etherpad expects plugins to be installed — via the admin
11
+ UI (**Admin → Manage Plugins → Search** for `ep_table_of_contents` and
12
+ click *Install*), or from the Etherpad root directory:
13
+
14
+ ```sh
15
+ pnpm run plugins install ep_table_of_contents
16
+ ```
17
+
18
+ > ⚠️ Don't run `npm i ep_table_of_contents` yourself from the Etherpad
19
+ > source tree. It adds the plugin to the top-level `package.json` but
20
+ > doesn't hook it into Etherpad's own plugin registry, which can leave
21
+ > Etherpad unable to start with `npm ls` errors (see #154).
22
+
23
+ After installing, restart Etherpad.
24
+
8
25
  ## Configuration
9
26
 
10
27
  If you want to have the TOC shown by default, add following snippet to your `settings.json`:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ep_table_of_contents",
3
- "version": "0.3.133",
3
+ "version": "0.3.135",
4
4
  "description": "View a table of contents for your pad",
5
5
  "author": {
6
6
  "name": "John McLear",
@@ -1,14 +1,23 @@
1
- /* global tableOfContents */
2
1
  'use strict';
3
2
 
3
+ // aceEditEvent fires inside ACE's inner iframe, which has its own `globalThis`
4
+ // separate from the outer pad page where toc.js runs. Reach across the
5
+ // iframe boundary via `window.top` (the topmost frame, i.e. the outer pad
6
+ // page). If toc.js hasn't executed yet — e.g. during very early pad init —
7
+ // silently skip; it will be called again on the next edit event.
8
+ const getToc = () => (typeof globalThis !== 'undefined' && globalThis.tableOfContents) ||
9
+ (window.top && window.top.tableOfContents) || null;
10
+
4
11
  exports.aceEditEvent = (hookName, args) => {
5
12
  // dont do anything on idle work timer, wait for changes..
6
13
  if (args.callstack && args.callstack.type === 'idleWorkTimer') return false;
14
+ const toc = getToc();
15
+ if (!toc) return;
7
16
  if (args.rep) {
8
- tableOfContents.showPosition(args.rep);
17
+ toc.showPosition(args.rep);
9
18
  }
10
19
 
11
20
  if ($('#toc:visible').length > 0) {
12
- tableOfContents.update();
21
+ toc.update();
13
22
  }
14
23
  };
@@ -1,6 +1,14 @@
1
- /* global tableOfContents */
2
1
  'use strict';
3
2
 
3
+ // postAceInit is loaded as a CommonJS plugin hook module; its scope is not
4
+ // the same as the <script> tag that loads toc.js, so `tableOfContents` is
5
+ // not visible via the normal scope chain. Look it up explicitly on the
6
+ // topmost window (where toc.js runs) with a globalThis fallback for the
7
+ // case where both happen to share a realm.
8
+ const getToc = () => (typeof globalThis !== 'undefined' && globalThis.tableOfContents) ||
9
+ (window.top && window.top.tableOfContents) ||
10
+ window.tableOfContents || null;
11
+
4
12
  exports.postAceInit = () => {
5
13
  if (!$('#editorcontainerbox').hasClass('flex-layout')) {
6
14
  $.gritter.add({
@@ -11,28 +19,30 @@ exports.postAceInit = () => {
11
19
  class_name: 'error',
12
20
  });
13
21
  }
22
+ const toc = getToc();
23
+ if (!toc) return;
14
24
  const optionToc = $('#options-toc');
15
25
  /* on click */
16
26
  optionToc.on('click', () => {
17
27
  if (optionToc.is(':checked')) {
18
- tableOfContents.enable(); // enables line tocping
28
+ toc.enable(); // enables line tocping
19
29
  } else {
20
30
  optionToc.prop('checked', false);
21
- tableOfContents.disable(); // disables line tocping
31
+ toc.disable(); // disables line tocping
22
32
  }
23
33
  });
24
34
  if (optionToc.is(':checked')) {
25
- tableOfContents.enable();
35
+ toc.enable();
26
36
  } else {
27
- tableOfContents.disable();
37
+ toc.disable();
28
38
  }
29
39
 
30
- const tocParam = tableOfContents.getParam('toc');
40
+ const tocParam = toc.getParam('toc');
31
41
  if (tocParam === true) {
32
42
  optionToc.prop('checked', true);
33
- tableOfContents.enable();
43
+ toc.enable();
34
44
  } else if (tocParam === false) {
35
45
  optionToc.prop('checked', false);
36
- tableOfContents.disable();
46
+ toc.disable();
37
47
  }
38
48
  };
package/static/js/toc.js CHANGED
@@ -63,7 +63,14 @@ if (typeof $ !== 'undefined') {
63
63
  });
64
64
  }
65
65
 
66
- const tableOfContents = {
66
+ // Expose on globalThis so other plugin scripts (postAceInit.js,
67
+ // aceEditEvent.js) that run in their own CommonJS-style module scopes can
68
+ // still reach it. Top-level `const` in a <script> tag is script-scoped,
69
+ // not a global, so without this the bare `tableOfContents` identifier in
70
+ // those modules throws `ReferenceError: tableOfContents is not defined`
71
+ // on pad load. globalThis resolves to `window` in the browser and to
72
+ // `global` in Node.js, so the Node unit tests keep working too.
73
+ const tableOfContents = globalThis.tableOfContents = {
67
74
 
68
75
  enable() {
69
76
  $('#toc').show();