ep_markdown_toc 1.0.6 → 1.0.8

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/index.js CHANGED
@@ -12,7 +12,13 @@ exports.eejsBlock_styles = (hook, context) => {
12
12
 
13
13
  exports.eejsBlock_editbarMenuRight = (hookName, args, cb) => {
14
14
  // console.log("MENU RIGHT");
15
- args.content = eejs.require('ep_markdown_toc/templates/markdownButton.ejs') + args.content;
15
+ args.content = eejs.require('ep_markdown_toc/templates/tocToggleButton.ejs') +
16
+ eejs.require('ep_markdown_toc/templates/markdownButton.ejs') + args.content;
17
+ return cb();
18
+ };
19
+
20
+ exports.eejsBlock_dd_view = (hookName, args, cb) => {
21
+ args.content += '<li><a href="#" id="markdown-toc-toggle-menu">Markdown TOC</a></li>';
16
22
  return cb();
17
23
  };
18
24
 
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "ep_markdown_toc",
3
3
  "description": "Provides markdown-based heading detection and TOC for Etherpad, used in Octomode.",
4
- "version": "1.0.6",
4
+ "version": "1.0.8",
5
5
  "author": {
6
6
  "name": "hrk",
7
7
  "email": "heerko@hackersanddesigners.nl"
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "https://github.com/heerko/ep_markdown_toc"
11
+ "url": "git+https://github.com/heerko/ep_markdown_toc.git"
12
12
  },
13
13
  "dependencies": {
14
14
  "showdown": "*"
@@ -3,6 +3,7 @@
3
3
  let _editorInfo = null; // Both no longer used atm, but leaving them for now.
4
4
  let _ace;
5
5
  const tags = ['h1', 'h2', 'h3', 'h4'];
6
+ let plainPasteEnabled = true;
6
7
 
7
8
  /* Load the css in the editor iframe */
8
9
  exports.aceEditorCSS = function() {
@@ -15,6 +16,8 @@ exports.aceEditorCSS = function() {
15
16
  exports.postAceInit = (hook, context) => {
16
17
  // store a reference to the editor for later
17
18
  _ace = context.ace;
19
+ // Initialize plain paste handler (if enabled).
20
+ maybeInitPlainPaste(context);
18
21
  updateTOC();
19
22
  };
20
23
 
@@ -71,6 +74,14 @@ exports.postToolbarInit = () => {
71
74
  $('#markdown-cheat').toggleClass('popup-show');
72
75
  });
73
76
 
77
+ const toggleToc = (event) => {
78
+ if (event) event.preventDefault();
79
+ $('#options-hideToc').click();
80
+ };
81
+
82
+ $('#markdown-toc-toggle').on('click', toggleToc);
83
+ $('#markdown-toc-toggle-menu').on('click', toggleToc);
84
+
74
85
  initSettingsUI();
75
86
  };
76
87
 
@@ -153,6 +164,7 @@ but it maybe possible to manipulate the list from settings.json?
153
164
  */
154
165
  function initSettingsUI() {
155
166
  const padcookie = require('ep_etherpad-lite/static/js/pad_cookie').padcookie;
167
+ const plainPaste = require('./plain_paste');
156
168
 
157
169
  let prefs = padcookie.getPref('userPrefs') || {};
158
170
 
@@ -169,6 +181,10 @@ function initSettingsUI() {
169
181
  prefs.styleHeadings = true; // also true
170
182
  padcookie.setPref('userPrefs', prefs);
171
183
  }
184
+ if (typeof prefs.plainPaste === 'undefined') {
185
+ prefs.plainPaste = true; // default to on
186
+ padcookie.setPref('userPrefs', prefs);
187
+ }
172
188
 
173
189
  // apply the headings class to the inner iframe if set
174
190
  const padOuter = document.querySelector('iframe[name="ace_outer"]');
@@ -203,6 +219,22 @@ function initSettingsUI() {
203
219
  bindToggleSetting('#options-hideToc', 'hide-toc', 'hideToc');
204
220
  bindToggleSetting('#options-hideButtons', 'hide-buttons', 'hideButtons');
205
221
  bindToggleSetting('#options-styleHeadings', 'style-md-headings', 'styleHeadings');
222
+
223
+ // Plain paste toggle
224
+ const plainPasteCheckbox = $('#options-plainPaste');
225
+ plainPasteCheckbox.prop('checked', prefs.plainPaste === true);
226
+ plainPasteEnabled = prefs.plainPaste === true;
227
+ plainPasteCheckbox.on('change', function () {
228
+ const isChecked = $(this).is(':checked');
229
+ prefs.plainPaste = isChecked;
230
+ plainPasteEnabled = isChecked;
231
+ padcookie.setPref('userPrefs', prefs);
232
+ if (isChecked) {
233
+ plainPaste.ensure(context);
234
+ } else {
235
+ plainPaste.disable();
236
+ }
237
+ });
206
238
  }
207
239
 
208
240
  /* functions stolen from ep_headings2 */
@@ -217,4 +249,13 @@ exports.aceAttribsToClasses = (hookName, context) => {
217
249
  if (context.key === 'heading') {
218
250
  return [`heading:${context.value}`];
219
251
  }
220
- };
252
+ };
253
+
254
+ /*
255
+ Plain paste integration: init if enabled and available.
256
+ */
257
+ function maybeInitPlainPaste(context) {
258
+ if (!plainPasteEnabled) return;
259
+ //const plainPaste = require('./plain_paste');
260
+ //plainPaste.ensure(context);
261
+ }
@@ -0,0 +1,60 @@
1
+ // Force plain-text paste: intercept paste and insert text/plain only.
2
+ let bound = false;
3
+ let currentBody = null;
4
+ let currentHandler = null;
5
+
6
+ // Locate the inner editor window either from context or via DOM.
7
+ const getInnerWindow = (context) => {
8
+ if (context?.editorInfo?.ace_innerWin) return context.editorInfo.ace_innerWin;
9
+ const outer = document.querySelector('iframe[name="ace_outer"]');
10
+ const inner = outer?.contentDocument?.querySelector('iframe[name="ace_inner"]');
11
+ return inner?.contentWindow || null;
12
+ };
13
+
14
+ const install = (context) => {
15
+ if (bound) return;
16
+
17
+ const editor = context?.editorInfo?.editor;
18
+ const callWithAce =
19
+ editor && typeof editor.callWithAce === 'function'
20
+ ? editor.callWithAce.bind(editor)
21
+ : null;
22
+ const innerWin = getInnerWindow(context);
23
+ const body = innerWin?.document?.body;
24
+
25
+ if (!callWithAce || !body) return;
26
+
27
+ const handlePaste = (e) => {
28
+ const clipboard = e.clipboardData || (e.originalEvent && e.originalEvent.clipboardData);
29
+ const text = clipboard
30
+ ? clipboard.getData('text/plain') || clipboard.getData('text')
31
+ : '';
32
+ if (!text) return;
33
+
34
+ e.preventDefault();
35
+ e.stopPropagation();
36
+ e.stopImmediatePropagation?.();
37
+ callWithAce((ace) => {
38
+ if (!ace || typeof ace.ace_getRep !== 'function' || typeof ace.ace_replaceRange !== 'function') return;
39
+ const rep = ace.ace_getRep();
40
+ if (!rep || !rep.selStart || !rep.selEnd) return;
41
+ ace.ace_replaceRange(rep.selStart, rep.selEnd, text);
42
+ }, 'plain-paste', true);
43
+ };
44
+
45
+ body.addEventListener('paste', handlePaste, true);
46
+ bound = true;
47
+ currentBody = body;
48
+ currentHandler = handlePaste;
49
+ };
50
+
51
+ exports.ensure = (context) => install(context);
52
+
53
+ exports.disable = () => {
54
+ if (bound && currentBody && currentHandler) {
55
+ currentBody.removeEventListener('paste', currentHandler, true);
56
+ }
57
+ bound = false;
58
+ currentBody = null;
59
+ currentHandler = null;
60
+ };
@@ -14,4 +14,9 @@
14
14
  <input type="checkbox" id="options-styleHeadings" />
15
15
  <label for="options-styleHeadings" aria-label="Enable/Disable styling of the markdown headings">Style Markdown headings</label>
16
16
  </p>
17
- </fieldset>
17
+
18
+ <p>
19
+ <input type="checkbox" id="options-plainPaste" />
20
+ <label for="options-plainPaste" aria-label="Force plain-text paste">Force plain-text paste</label>
21
+ </p>
22
+ </fieldset>
@@ -0,0 +1,6 @@
1
+ <li data-key="ep_markdown_toc-toggle" data-type="button">
2
+ <a id="ep_markdown_toc-a" title="Toggle TOC">
3
+ <button id="markdown-toc-toggle" class="buttonicon buttonicon-insertunorderedlist" title="Toggle TOC"></button>
4
+ </a>
5
+ </li>
6
+ <li class="separator"></li>