ponkotsu-md-editor 0.2.16 → 0.2.18

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 44c0d57085b26248050128b50dd4e4651198ed4d6805cc40eb4a6db417e20a91
4
- data.tar.gz: 7ebe6787dc0b1591c08995be8640f68ad6aaec0e25d1cce0212631db5dc54064
3
+ metadata.gz: 0cee3f1cda79e611392ecd15c3f373a0e65de3ae4895c875878c47108a265ab8
4
+ data.tar.gz: 194fb5f55df7e26a535a1209303e0316bc3d107f1635a1ec077782ea77c6b451
5
5
  SHA512:
6
- metadata.gz: fc5a9675a51a6b64f976a7af0b3b8ef1b273906f48f4ce086353bbe65ee2a7400acd9cf970c66979762511653a36520375ec74693dbe1567a7639c7a4aa94016
7
- data.tar.gz: a0c6d1de3b9dd58f7b4e0d3f6e06d8aa2834ff3da5cbdc24a0ad3a1a4e27010e4b12f70a33f881c1e438cc32cd0b5002f09cd5a24bd8abe0d0fe7303c102afe5
6
+ metadata.gz: 313668a4f9c9d78b212ee0c28413f0854fa1e4656137bb2b6f2397b201e131f3e413536f786daf2c00acba0719108b1c5b4ce296017367fab3c26b30b4431340
7
+ data.tar.gz: 166ddd5ecd7ad645305069a5c3649e5b949ae82eaacf99eef700a187f8a56c8195f5dbdce668d7897733acb3047d18968a1b3d29dd04d860346a93f4ab60ae58
@@ -1,6 +1,19 @@
1
1
  (function() {
2
2
  'use strict';
3
3
 
4
+ // Debounce function for delayed execution
5
+ function debounce(func, wait) {
6
+ let timeout;
7
+ return function executedFunction(...args) {
8
+ const later = () => {
9
+ clearTimeout(timeout);
10
+ func(...args);
11
+ };
12
+ clearTimeout(timeout);
13
+ timeout = setTimeout(later, wait);
14
+ };
15
+ }
16
+
4
17
  // Safe DOM element retrieval
5
18
  function getElement(selector) {
6
19
  try {
@@ -23,7 +36,7 @@
23
36
  const syncToHidden = () => {
24
37
  hiddenField.value = (textarea.innerText || '').replaceAll('\u00A0', ' ');
25
38
  };
26
- textarea.addEventListener('input', syncToHidden);
39
+ textarea.addEventListener('input', debounce(syncToHidden, 150));
27
40
  textarea.addEventListener('blur', syncToHidden);
28
41
  // 初期化時にも同期
29
42
  syncToHidden();
@@ -42,7 +55,7 @@
42
55
  updatePlaceholderVisibility();
43
56
 
44
57
  // 入力時にプレースホルダの表示/非表示を制御
45
- textarea.addEventListener('input', updatePlaceholderVisibility);
58
+ textarea.addEventListener('input', debounce(updatePlaceholderVisibility, 150));
46
59
  textarea.addEventListener('blur', updatePlaceholderVisibility);
47
60
  }
48
61
  } else {
@@ -86,20 +99,44 @@
86
99
  beforeEndRange.setEnd(range.endContainer, range.endOffset);
87
100
  let endPos = beforeEndRange.toString().length;
88
101
 
89
- // --- 再スキャンで<br>と改行の取りこぼしを防ぐ ---
90
102
  function scanOffset(pos) {
103
+ // キャッシュを追加
104
+ if (this._scanOffsetCache && this._scanOffsetCache.pos === pos) {
105
+ return this._scanOffsetCache.result;
106
+ }
107
+
108
+ // HTML全体を一度だけ取得(これは良い改善)
109
+ const fullHTML = textarea.innerHTML;
110
+ const fullText = textarea.innerText;
111
+
91
112
  let offset = pos;
92
113
  let lastAdded = -1;
93
- while (true) {
94
- const htmlUpTo = textarea.innerHTML.substring(0, offset);
114
+ let iterations = 0;
115
+ const MAX_ITERATIONS = 100; // より安全な上限
116
+
117
+ while (iterations < MAX_ITERATIONS) {
118
+ const htmlUpTo = fullHTML.substring(0, offset);
119
+ const textUpTo = fullText.substring(0, offset);
120
+
121
+ // 元の正規表現を維持(安全性優先)
95
122
  const brCount = (htmlUpTo.match(/<br\s*\/?>(?![\w\W]*<)/g) || []).length;
96
- const textUpTo = textarea.innerText.substring(0, offset);
97
123
  const nlCount = (textUpTo.match(/\n/g) || []).length;
124
+
98
125
  const added = brCount + nlCount;
99
126
  if (added === lastAdded) break;
127
+
100
128
  offset = pos + added;
101
129
  lastAdded = added;
130
+ iterations++;
131
+ }
132
+
133
+ if (iterations >= MAX_ITERATIONS) {
134
+ console.warn('scanOffset: Maximum iterations reached, possible infinite loop');
102
135
  }
136
+
137
+ // 結果をキャッシュ
138
+ this._scanOffsetCache = { pos: pos, result: offset };
139
+
103
140
  return offset;
104
141
  }
105
142
  startPos = scanOffset(startPos);
@@ -117,7 +154,7 @@
117
154
  caretPosition.end = textarea.selectionEnd;
118
155
  }
119
156
  };
120
- textarea.addEventListener('input', saveCaretPosition);
157
+ textarea.addEventListener('input', debounce(saveCaretPosition, 100));
121
158
  textarea.addEventListener('keyup', saveCaretPosition);
122
159
  textarea.addEventListener('click', saveCaretPosition);
123
160
  }
@@ -692,7 +729,16 @@
692
729
  }
693
730
  }
694
731
 
732
+ const analyzeHtmlCache = new Map();
733
+
695
734
  function analyzeHtml(target, isCountEmptyDiv = false) {
735
+
736
+ const cacheKey = `${target}_${isCountEmptyDiv}`;
737
+
738
+ if (analyzeHtmlCache.has(cacheKey)) {
739
+ return analyzeHtmlCache.get(cacheKey);
740
+ }
741
+
696
742
  let lines = [];
697
743
  let remain = target;
698
744
 
@@ -758,6 +804,12 @@
758
804
  }
759
805
  }
760
806
 
807
+ if (analyzeHtmlCache.size > 100) {
808
+ const firstKey = analyzeHtmlCache.keys().next().value;
809
+ analyzeHtmlCache.delete(firstKey);
810
+ }
811
+
812
+ analyzeHtmlCache.set(cacheKey, lines);
761
813
  return lines;
762
814
  }
763
815
 
@@ -1975,19 +2027,6 @@
1975
2027
  }
1976
2028
  }
1977
2029
 
1978
- // Debounce function for delayed execution
1979
- function debounce(func, wait) {
1980
- let timeout;
1981
- return function executedFunction(...args) {
1982
- const later = () => {
1983
- clearTimeout(timeout);
1984
- func(...args);
1985
- };
1986
- clearTimeout(timeout);
1987
- timeout = setTimeout(later, wait);
1988
- };
1989
- }
1990
-
1991
2030
  // Keyboard shortcuts
1992
2031
  if (textarea) {
1993
2032
  textarea.addEventListener('keydown', function(e) {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PonkotsuMdEditor
4
- VERSION = "0.2.16"
4
+ VERSION = "0.2.18"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ponkotsu-md-editor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.16
4
+ version: 0.2.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - dhq_boiler