ep_data_tables 0.0.9 → 0.0.95

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ep_data_tables",
3
- "version": "0.0.9",
3
+ "version": "0.0.95",
4
4
  "description": "BETA - etherpad tables plugin, compatible with other character/line based styling and other features",
5
5
  "author": {
6
6
  "name": "DCastelone",
@@ -1,4 +1,15 @@
1
1
  const ATTR_TABLE_JSON = 'tbljson';
2
+ // Global guard: Chrome/macOS sometimes loads the same plugin script twice due to a
3
+ // subtle preload/import timing quirk, causing duplicate aceInitialized hooks that
4
+ // explode into large duplicate-row changesets. Bail early on re-entry.
5
+ if (typeof window !== 'undefined') {
6
+ if (window.__epDataTablesLoaded) {
7
+ console.debug('[ep_data_tables] Duplicate client_hooks.js load suppressed');
8
+ // eslint-disable-next-line no-useless-return
9
+ return; // Abort evaluation of the rest of the module
10
+ }
11
+ window.__epDataTablesLoaded = true;
12
+ }
2
13
  const ATTR_CELL = 'td';
3
14
  const ATTR_CLASS_PREFIX = 'tbljson-';
4
15
  const log = (...m) => console.debug('[ep_data_tables:client_hooks]', ...m);
@@ -623,7 +634,8 @@ function buildTableFromDelimitedHTML(metadata, innerHTMLSegments) {
623
634
  const cellsHtml = innerHTMLSegments.map((segment, index) => {
624
635
  const textOnly = (segment || '').replace(/<[^>]*>/g, '').replace(/&nbsp;/ig, ' ').trim();
625
636
  let modifiedSegment = segment || '';
626
- const isEmpty = !segment || textOnly === '';
637
+ const containsImage = /\bimage-placeholder\b/.test(modifiedSegment);
638
+ const isEmpty = (!segment || textOnly === '') && !containsImage;
627
639
  if (isEmpty) {
628
640
  const cellClass = encodedTbljsonClass ? `${encodedTbljsonClass} tblCell-${index}` : `tblCell-${index}`;
629
641
  modifiedSegment = `<span class="${cellClass}">&nbsp;</span>`;
@@ -862,8 +874,8 @@ exports.acePostWriteDomLineHTML = function (hook_name, args, cb) {
862
874
  .replace(/<span class="ep-data_tables-caret-anchor"[^>]*><\/span>/ig, '')
863
875
  .replace(/\r?\n/g, ' ')
864
876
  .replace(/<br\s*\/?>/gi, ' ')
865
- .replace(/\u00A0/gu, ' ')
866
- .replace(/[\u200B\u200C\u200D\uFEFF]/g, '')
877
+ // .replace(/\u00A0/gu, ' ')
878
+ // .replace(/[\u200B\u200C\u200D\uFEFF]/g, '')
867
879
  .replace(/\s+/g, ' ');
868
880
  const htmlSegments = sanitizedHTMLForSplit.split(DELIMITER);
869
881
 
@@ -1937,6 +1949,15 @@ exports.aceInitialized = (h, ctx) => {
1937
1949
  if (!e || e._epDataTablesNormalized) return;
1938
1950
  const t = e.inputType || '';
1939
1951
  const dataStr = typeof e.data === 'string' ? e.data : '';
1952
+
1953
+ // If this NBSP is flanked by ZWSPs we are inside an image placeholder.
1954
+ // In that case leave it untouched so caret math stays correct.
1955
+ if (dataStr === '\u00A0' && rep && rep.selStart) {
1956
+ const lineText = rep.lines.atIndex(rep.selStart[0])?.text || '';
1957
+ const pos = rep.selStart[1]; // caret is before the NBSP
1958
+ if (lineText.slice(pos - 1, pos + 2) === '\u200B\u00A0\u200B') return;
1959
+ }
1960
+
1940
1961
  const hasSoftWs = /[\r\n\u00A0]/.test(dataStr); // include NBSP (U+00A0)
1941
1962
  const isSoftBreak = t === 'insertParagraph' || t === 'insertLineBreak' || hasSoftWs;
1942
1963
  if (!isSoftBreak) return;
@@ -4890,3 +4911,4 @@ exports.aceUndoRedo = (hook, ctx) => {
4890
4911
  // log(`${logPrefix} Error details:`, { message: e.message, stack: e.stack });
4891
4912
  }
4892
4913
  };
4914
+