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 +17 -0
- package/package.json +1 -1
- package/static/js/aceEditEvent.js +12 -3
- package/static/js/postAceInit.js +18 -8
- package/static/js/toc.js +8 -1
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,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
|
-
|
|
17
|
+
toc.showPosition(args.rep);
|
|
9
18
|
}
|
|
10
19
|
|
|
11
20
|
if ($('#toc:visible').length > 0) {
|
|
12
|
-
|
|
21
|
+
toc.update();
|
|
13
22
|
}
|
|
14
23
|
};
|
package/static/js/postAceInit.js
CHANGED
|
@@ -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
|
-
|
|
28
|
+
toc.enable(); // enables line tocping
|
|
19
29
|
} else {
|
|
20
30
|
optionToc.prop('checked', false);
|
|
21
|
-
|
|
31
|
+
toc.disable(); // disables line tocping
|
|
22
32
|
}
|
|
23
33
|
});
|
|
24
34
|
if (optionToc.is(':checked')) {
|
|
25
|
-
|
|
35
|
+
toc.enable();
|
|
26
36
|
} else {
|
|
27
|
-
|
|
37
|
+
toc.disable();
|
|
28
38
|
}
|
|
29
39
|
|
|
30
|
-
const tocParam =
|
|
40
|
+
const tocParam = toc.getParam('toc');
|
|
31
41
|
if (tocParam === true) {
|
|
32
42
|
optionToc.prop('checked', true);
|
|
33
|
-
|
|
43
|
+
toc.enable();
|
|
34
44
|
} else if (tocParam === false) {
|
|
35
45
|
optionToc.prop('checked', false);
|
|
36
|
-
|
|
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
|
-
|
|
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();
|