ide-assi 0.371.0 → 0.373.0

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.
@@ -234776,7 +234776,7 @@ function requireDiffMatchPatch () {
234776
234776
 
234777
234777
  var diffMatchPatchExports = requireDiffMatchPatch();
234778
234778
 
234779
- // Diff 데코레이션을 위한 StateField 정의 (asis 에디터용)
234779
+ // Diff 데코레이션을 위한 StateField 정의 (변동 없음)
234780
234780
  const asisDiffDecorations = StateField.define({
234781
234781
  create() { return Decoration.none; },
234782
234782
  update(decorations, tr) {
@@ -234790,7 +234790,6 @@ const asisDiffDecorations = StateField.define({
234790
234790
  provide: f => EditorView.decorations.from(f)
234791
234791
  });
234792
234792
 
234793
- // Diff 데코레이션을 위한 StateField 정의 (tobe 에디터용)
234794
234793
  const tobeDiffDecorations = StateField.define({
234795
234794
  create() { return Decoration.none; },
234796
234795
  update(decorations, tr) {
@@ -234804,7 +234803,6 @@ const tobeDiffDecorations = StateField.define({
234804
234803
  provide: f => EditorView.decorations.from(f)
234805
234804
  });
234806
234805
 
234807
- // 데코레이션 업데이트를 위한 Effect (트랜잭션에 포함시켜 상태 변경 알림)
234808
234806
  const setAsisDecorationsEffect = StateEffect.define();
234809
234807
  const setTobeDecorationsEffect = StateEffect.define();
234810
234808
 
@@ -234817,10 +234815,9 @@ class IdeDiff extends HTMLElement {
234817
234815
 
234818
234816
  #languageCompartment = new Compartment();
234819
234817
 
234820
- // ⭐️ 스크롤 동기화 활성/비활성화 플래그 및 핸들러 참조
234821
234818
  #isScrollSyncActive = false;
234822
- _asisScrollHandler = null; // 클래스 속성으로 선언하여 removeEventListener에서 참조 가능
234823
- _tobeScrollHandler = null; // 클래스 속성으로 선언하여 removeEventListener에서 참조 가능
234819
+ _asisScrollHandler = null;
234820
+ _tobeScrollHandler = null;
234824
234821
 
234825
234822
 
234826
234823
  constructor() {
@@ -234831,38 +234828,35 @@ class IdeDiff extends HTMLElement {
234831
234828
  connectedCallback() {
234832
234829
  this.shadowRoot.innerHTML = `
234833
234830
  <style>
234834
- /* ninegrid CSS 및 필요한 기본 스타일 */
234831
+ /* ninegrid CSS 및 필요한 기본 스타일 (변동 없음) */
234835
234832
  @import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/ideDiff.css";
234836
234833
  ${ninegrid.getCustomPath(this, "ideDiff.css")}
234837
234834
 
234838
- /* CodeMirror를 위한 기본적인 Flexbox 레이아웃 */
234835
+ /* CodeMirror를 위한 기본적인 Flexbox 레이아웃 (변동 없음) */
234839
234836
  .wrapper {
234840
234837
  display: flex;
234841
234838
  width: 100%;
234842
- height: 100%; /* 부모의 높이를 채우도록 설정 */
234843
- overflow: hidden; /* 내부 스크롤을 위해 overflow 처리 */
234839
+ height: 100%;
234840
+ overflow: hidden;
234844
234841
  }
234845
234842
  .panel {
234846
- flex: 1; /* 패널들이 남은 공간을 채우도록 */
234847
- overflow: hidden; /* CodeMirror EditorView 자체가 스크롤을 처리 */
234848
- min-width: 0; /* Flexbox 아이템이 content 때문에 늘어나는 것을 방지 */
234843
+ flex: 1;
234844
+ overflow: hidden;
234845
+ min-width: 0;
234849
234846
  }
234850
234847
  .cm-editor {
234851
- height: 100%; /* EditorView가 부모 div의 높이를 채우도록 */
234848
+ height: 100%;
234852
234849
  }
234853
234850
 
234854
- /* Diff 시각화를 위한 CSS 클래스 */
234855
- /* 전체 배경색 */
234856
- .cm-inserted-line-bg { background-color: #e6ffe6; } /* 연한 녹색 */
234857
- .cm-deleted-line-bg { background-color: #ffe6e6; } /* 연한 빨간색 */
234858
-
234859
- /* 인라인(단어/문자) 변경 강조 */
234851
+ /* Diff 시각화를 위한 CSS 클래스 (변동 없음) */
234852
+ .cm-inserted-line-bg { background-color: #e6ffe6; }
234853
+ .cm-deleted-line-bg { background-color: #ffe6e6; }
234860
234854
  .cm-inserted-inline {
234861
- background-color: #90ee90; /* 밝은 녹색 */
234855
+ background-color: #90ee90;
234862
234856
  font-weight: bold;
234863
234857
  }
234864
234858
  .cm-deleted-inline {
234865
- background-color: #ff9999; /* 밝은 빨간색 */
234859
+ background-color: #ff9999;
234866
234860
  text-decoration: line-through;
234867
234861
  font-weight: bold;
234868
234862
  }
@@ -234923,11 +234917,10 @@ class IdeDiff extends HTMLElement {
234923
234917
  EditorState.readOnly.of(true),
234924
234918
  this.#languageCompartment.of(javascript()),
234925
234919
  asisDiffDecorations,
234926
- // ⭐️ 중요: 뷰가 DOM에 완전히 렌더링될 때까지 기다립니다.
234920
+ // ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
234927
234921
  EditorView.updateListener.of((update) => {
234928
- // 뷰의 DOM 내용이 비어있지 않고, 아직 초기 로드가 완료되지 않았다면
234929
234922
  if (update.view.contentDOM.firstChild && !update.view._initialAsisContentLoaded) {
234930
- update.view._initialAsisContentLoaded = true; // 플래그 설정
234923
+ update.view._initialAsisContentLoaded = true;
234931
234924
  console.log("CodeMirror ASIS view is ready for initial content.");
234932
234925
  }
234933
234926
  })
@@ -234946,11 +234939,10 @@ class IdeDiff extends HTMLElement {
234946
234939
  EditorState.readOnly.of(true),
234947
234940
  this.#languageCompartment.of(javascript()),
234948
234941
  tobeDiffDecorations,
234949
- // ⭐️ 중요: 뷰가 DOM에 완전히 렌더링될 때까지 기다립니다.
234942
+ // ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
234950
234943
  EditorView.updateListener.of((update) => {
234951
- // 뷰의 DOM 내용이 비어있지 않고, 아직 초기 로드가 완료되지 않았다면
234952
234944
  if (update.view.contentDOM.firstChild && !update.view._initialTobeContentLoaded) {
234953
- update.view._initialTobeContentLoaded = true; // 플래그 설정
234945
+ update.view._initialTobeContentLoaded = true;
234954
234946
  console.log("CodeMirror TOBE view is ready for initial content.");
234955
234947
  }
234956
234948
  })
@@ -234959,14 +234951,11 @@ class IdeDiff extends HTMLElement {
234959
234951
  parent: this.#tobeEditorEl
234960
234952
  });
234961
234953
 
234962
- // ⭐️ 초기 스크롤 동기화는 여기서 설정만 하고, initialize에서 활성화 제어
234963
234954
  this.#setupScrollSync();
234964
234955
  };
234965
234956
 
234966
- // ⭐️ 스크롤 리스너를 제어할 수 있도록 플래그 및 클래스 메서드 사용
234967
234957
  #setupScrollSync = () => {
234968
- // 기존 리스너가 있다면 제거 (중복 방지 및 disconnectedCallback에서 제거 용이)
234969
- if (this._asisScrollHandler) { // 핸들러가 이미 할당되어 있다면
234958
+ if (this._asisScrollHandler) {
234970
234959
  this.#asisEditorView.scrollDOM.removeEventListener('scroll', this._asisScrollHandler);
234971
234960
  this.#tobeEditorView.scrollDOM.removeEventListener('scroll', this._tobeScrollHandler);
234972
234961
  }
@@ -234975,7 +234964,7 @@ class IdeDiff extends HTMLElement {
234975
234964
  let scrollingB = false;
234976
234965
 
234977
234966
  this._asisScrollHandler = () => {
234978
- if (!this.#isScrollSyncActive) return; // 활성화되지 않았으면 스킵
234967
+ if (!this.#isScrollSyncActive) return;
234979
234968
 
234980
234969
  if (!scrollingB) {
234981
234970
  scrollingA = true;
@@ -234986,7 +234975,7 @@ class IdeDiff extends HTMLElement {
234986
234975
  };
234987
234976
 
234988
234977
  this._tobeScrollHandler = () => {
234989
- if (!this.#isScrollSyncActive) return; // 활성화되지 않았으면 스킵
234978
+ if (!this.#isScrollSyncActive) return;
234990
234979
 
234991
234980
  if (!scrollingA) {
234992
234981
  scrollingB = true;
@@ -235000,7 +234989,6 @@ class IdeDiff extends HTMLElement {
235000
234989
  this.#tobeEditorView.scrollDOM.addEventListener('scroll', this._tobeScrollHandler);
235001
234990
  };
235002
234991
 
235003
- // #applyDiffDecorations 함수 (이전 수정본과 동일, Text.of 사용)
235004
234992
  #applyDiffDecorations = (asisSrc, tobeSrc) => {
235005
234993
  const dmp = new diffMatchPatchExports.diff_match_patch();
235006
234994
  const diffs = dmp.diff_main(asisSrc, tobeSrc);
@@ -235014,6 +235002,8 @@ class IdeDiff extends HTMLElement {
235014
235002
  let asisCursor = 0;
235015
235003
  let tobeCursor = 0;
235016
235004
 
235005
+ // ⭐️ 중요: 새로운 문서 내용을 기반으로 임시 Doc 객체를 생성합니다.
235006
+ // 이 Doc 객체를 사용하여 lineAt()을 호출합니다.
235017
235007
  const asisDoc = Text.of(asisSrc.split('\n'));
235018
235008
  const tobeDoc = Text.of(tobeSrc.split('\n'));
235019
235009
 
@@ -235123,8 +235113,7 @@ class IdeDiff extends HTMLElement {
235123
235113
  return;
235124
235114
  }
235125
235115
 
235126
- // 초기화 시작 스크롤 동기화 일시 중지
235127
- this.#isScrollSyncActive = false;
235116
+ this.#isScrollSyncActive = false; // 스크롤 동기화 일시 중지
235128
235117
 
235129
235118
  let langExtension;
235130
235119
  switch(language) {
@@ -235139,6 +235128,7 @@ class IdeDiff extends HTMLElement {
235139
235128
  const { asisEffect, tobeEffect } = this.#applyDiffDecorations(src1, src2);
235140
235129
 
235141
235130
  // 1단계: 텍스트 내용 변경과 언어 확장을 먼저 디스패치합니다.
235131
+ // 'to' 값을 현재 문서 길이 전체로 지정하여 정확한 교체를 보장합니다.
235142
235132
  this.#asisEditorView.dispatch({
235143
235133
  changes: { from: 0, to: this.#asisEditorView.state.doc.length, insert: src1 },
235144
235134
  effects: [
@@ -235153,10 +235143,9 @@ class IdeDiff extends HTMLElement {
235153
235143
  ]
235154
235144
  });
235155
235145
 
235156
- // 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화된 후,
235146
+ // ⭐️ 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화될 시간을 줍니다.
235157
235147
  // 다음 프레임에서 데코레이션 효과만 별도로 디스패치합니다.
235158
235148
  requestAnimationFrame(() => {
235159
- console.log(asisEffect, tobeEffect);
235160
235149
  this.#asisEditorView.dispatch({
235161
235150
  effects: [asisEffect]
235162
235151
  });
@@ -235164,8 +235153,8 @@ class IdeDiff extends HTMLElement {
235164
235153
  effects: [tobeEffect]
235165
235154
  });
235166
235155
 
235167
- // 3단계: 데코레이션까지 적용된 후 스크롤 동기화 활성화
235168
- // (필요하다면 여기도 requestAnimationFrame으로 더 지연시킬 수 있습니다.)
235156
+ // ⭐️ 3단계: 데코레이션까지 적용된 후 뷰가 다시 안정화될 시간을 한 번 더 줍니다.
235157
+ // 다음 프레임에서 스크롤 동기화를 활성화합니다.
235169
235158
  requestAnimationFrame(() => {
235170
235159
  this.#isScrollSyncActive = true;
235171
235160
  // 필요하다면 여기서 초기 스크롤 위치를 0으로 리셋하여 정렬을 보장할 수 있습니다.
@@ -234772,7 +234772,7 @@ function requireDiffMatchPatch () {
234772
234772
 
234773
234773
  var diffMatchPatchExports = requireDiffMatchPatch();
234774
234774
 
234775
- // Diff 데코레이션을 위한 StateField 정의 (asis 에디터용)
234775
+ // Diff 데코레이션을 위한 StateField 정의 (변동 없음)
234776
234776
  const asisDiffDecorations = StateField.define({
234777
234777
  create() { return Decoration.none; },
234778
234778
  update(decorations, tr) {
@@ -234786,7 +234786,6 @@ const asisDiffDecorations = StateField.define({
234786
234786
  provide: f => EditorView.decorations.from(f)
234787
234787
  });
234788
234788
 
234789
- // Diff 데코레이션을 위한 StateField 정의 (tobe 에디터용)
234790
234789
  const tobeDiffDecorations = StateField.define({
234791
234790
  create() { return Decoration.none; },
234792
234791
  update(decorations, tr) {
@@ -234800,7 +234799,6 @@ const tobeDiffDecorations = StateField.define({
234800
234799
  provide: f => EditorView.decorations.from(f)
234801
234800
  });
234802
234801
 
234803
- // 데코레이션 업데이트를 위한 Effect (트랜잭션에 포함시켜 상태 변경 알림)
234804
234802
  const setAsisDecorationsEffect = StateEffect.define();
234805
234803
  const setTobeDecorationsEffect = StateEffect.define();
234806
234804
 
@@ -234813,10 +234811,9 @@ class IdeDiff extends HTMLElement {
234813
234811
 
234814
234812
  #languageCompartment = new Compartment();
234815
234813
 
234816
- // ⭐️ 스크롤 동기화 활성/비활성화 플래그 및 핸들러 참조
234817
234814
  #isScrollSyncActive = false;
234818
- _asisScrollHandler = null; // 클래스 속성으로 선언하여 removeEventListener에서 참조 가능
234819
- _tobeScrollHandler = null; // 클래스 속성으로 선언하여 removeEventListener에서 참조 가능
234815
+ _asisScrollHandler = null;
234816
+ _tobeScrollHandler = null;
234820
234817
 
234821
234818
 
234822
234819
  constructor() {
@@ -234827,38 +234824,35 @@ class IdeDiff extends HTMLElement {
234827
234824
  connectedCallback() {
234828
234825
  this.shadowRoot.innerHTML = `
234829
234826
  <style>
234830
- /* ninegrid CSS 및 필요한 기본 스타일 */
234827
+ /* ninegrid CSS 및 필요한 기본 스타일 (변동 없음) */
234831
234828
  @import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/ideDiff.css";
234832
234829
  ${ninegrid.getCustomPath(this, "ideDiff.css")}
234833
234830
 
234834
- /* CodeMirror를 위한 기본적인 Flexbox 레이아웃 */
234831
+ /* CodeMirror를 위한 기본적인 Flexbox 레이아웃 (변동 없음) */
234835
234832
  .wrapper {
234836
234833
  display: flex;
234837
234834
  width: 100%;
234838
- height: 100%; /* 부모의 높이를 채우도록 설정 */
234839
- overflow: hidden; /* 내부 스크롤을 위해 overflow 처리 */
234835
+ height: 100%;
234836
+ overflow: hidden;
234840
234837
  }
234841
234838
  .panel {
234842
- flex: 1; /* 패널들이 남은 공간을 채우도록 */
234843
- overflow: hidden; /* CodeMirror EditorView 자체가 스크롤을 처리 */
234844
- min-width: 0; /* Flexbox 아이템이 content 때문에 늘어나는 것을 방지 */
234839
+ flex: 1;
234840
+ overflow: hidden;
234841
+ min-width: 0;
234845
234842
  }
234846
234843
  .cm-editor {
234847
- height: 100%; /* EditorView가 부모 div의 높이를 채우도록 */
234844
+ height: 100%;
234848
234845
  }
234849
234846
 
234850
- /* Diff 시각화를 위한 CSS 클래스 */
234851
- /* 전체 배경색 */
234852
- .cm-inserted-line-bg { background-color: #e6ffe6; } /* 연한 녹색 */
234853
- .cm-deleted-line-bg { background-color: #ffe6e6; } /* 연한 빨간색 */
234854
-
234855
- /* 인라인(단어/문자) 변경 강조 */
234847
+ /* Diff 시각화를 위한 CSS 클래스 (변동 없음) */
234848
+ .cm-inserted-line-bg { background-color: #e6ffe6; }
234849
+ .cm-deleted-line-bg { background-color: #ffe6e6; }
234856
234850
  .cm-inserted-inline {
234857
- background-color: #90ee90; /* 밝은 녹색 */
234851
+ background-color: #90ee90;
234858
234852
  font-weight: bold;
234859
234853
  }
234860
234854
  .cm-deleted-inline {
234861
- background-color: #ff9999; /* 밝은 빨간색 */
234855
+ background-color: #ff9999;
234862
234856
  text-decoration: line-through;
234863
234857
  font-weight: bold;
234864
234858
  }
@@ -234919,11 +234913,10 @@ class IdeDiff extends HTMLElement {
234919
234913
  EditorState.readOnly.of(true),
234920
234914
  this.#languageCompartment.of(javascript()),
234921
234915
  asisDiffDecorations,
234922
- // ⭐️ 중요: 뷰가 DOM에 완전히 렌더링될 때까지 기다립니다.
234916
+ // ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
234923
234917
  EditorView.updateListener.of((update) => {
234924
- // 뷰의 DOM 내용이 비어있지 않고, 아직 초기 로드가 완료되지 않았다면
234925
234918
  if (update.view.contentDOM.firstChild && !update.view._initialAsisContentLoaded) {
234926
- update.view._initialAsisContentLoaded = true; // 플래그 설정
234919
+ update.view._initialAsisContentLoaded = true;
234927
234920
  console.log("CodeMirror ASIS view is ready for initial content.");
234928
234921
  }
234929
234922
  })
@@ -234942,11 +234935,10 @@ class IdeDiff extends HTMLElement {
234942
234935
  EditorState.readOnly.of(true),
234943
234936
  this.#languageCompartment.of(javascript()),
234944
234937
  tobeDiffDecorations,
234945
- // ⭐️ 중요: 뷰가 DOM에 완전히 렌더링될 때까지 기다립니다.
234938
+ // ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
234946
234939
  EditorView.updateListener.of((update) => {
234947
- // 뷰의 DOM 내용이 비어있지 않고, 아직 초기 로드가 완료되지 않았다면
234948
234940
  if (update.view.contentDOM.firstChild && !update.view._initialTobeContentLoaded) {
234949
- update.view._initialTobeContentLoaded = true; // 플래그 설정
234941
+ update.view._initialTobeContentLoaded = true;
234950
234942
  console.log("CodeMirror TOBE view is ready for initial content.");
234951
234943
  }
234952
234944
  })
@@ -234955,14 +234947,11 @@ class IdeDiff extends HTMLElement {
234955
234947
  parent: this.#tobeEditorEl
234956
234948
  });
234957
234949
 
234958
- // ⭐️ 초기 스크롤 동기화는 여기서 설정만 하고, initialize에서 활성화 제어
234959
234950
  this.#setupScrollSync();
234960
234951
  };
234961
234952
 
234962
- // ⭐️ 스크롤 리스너를 제어할 수 있도록 플래그 및 클래스 메서드 사용
234963
234953
  #setupScrollSync = () => {
234964
- // 기존 리스너가 있다면 제거 (중복 방지 및 disconnectedCallback에서 제거 용이)
234965
- if (this._asisScrollHandler) { // 핸들러가 이미 할당되어 있다면
234954
+ if (this._asisScrollHandler) {
234966
234955
  this.#asisEditorView.scrollDOM.removeEventListener('scroll', this._asisScrollHandler);
234967
234956
  this.#tobeEditorView.scrollDOM.removeEventListener('scroll', this._tobeScrollHandler);
234968
234957
  }
@@ -234971,7 +234960,7 @@ class IdeDiff extends HTMLElement {
234971
234960
  let scrollingB = false;
234972
234961
 
234973
234962
  this._asisScrollHandler = () => {
234974
- if (!this.#isScrollSyncActive) return; // 활성화되지 않았으면 스킵
234963
+ if (!this.#isScrollSyncActive) return;
234975
234964
 
234976
234965
  if (!scrollingB) {
234977
234966
  scrollingA = true;
@@ -234982,7 +234971,7 @@ class IdeDiff extends HTMLElement {
234982
234971
  };
234983
234972
 
234984
234973
  this._tobeScrollHandler = () => {
234985
- if (!this.#isScrollSyncActive) return; // 활성화되지 않았으면 스킵
234974
+ if (!this.#isScrollSyncActive) return;
234986
234975
 
234987
234976
  if (!scrollingA) {
234988
234977
  scrollingB = true;
@@ -234996,7 +234985,6 @@ class IdeDiff extends HTMLElement {
234996
234985
  this.#tobeEditorView.scrollDOM.addEventListener('scroll', this._tobeScrollHandler);
234997
234986
  };
234998
234987
 
234999
- // #applyDiffDecorations 함수 (이전 수정본과 동일, Text.of 사용)
235000
234988
  #applyDiffDecorations = (asisSrc, tobeSrc) => {
235001
234989
  const dmp = new diffMatchPatchExports.diff_match_patch();
235002
234990
  const diffs = dmp.diff_main(asisSrc, tobeSrc);
@@ -235010,6 +234998,8 @@ class IdeDiff extends HTMLElement {
235010
234998
  let asisCursor = 0;
235011
234999
  let tobeCursor = 0;
235012
235000
 
235001
+ // ⭐️ 중요: 새로운 문서 내용을 기반으로 임시 Doc 객체를 생성합니다.
235002
+ // 이 Doc 객체를 사용하여 lineAt()을 호출합니다.
235013
235003
  const asisDoc = Text.of(asisSrc.split('\n'));
235014
235004
  const tobeDoc = Text.of(tobeSrc.split('\n'));
235015
235005
 
@@ -235119,8 +235109,7 @@ class IdeDiff extends HTMLElement {
235119
235109
  return;
235120
235110
  }
235121
235111
 
235122
- // 초기화 시작 스크롤 동기화 일시 중지
235123
- this.#isScrollSyncActive = false;
235112
+ this.#isScrollSyncActive = false; // 스크롤 동기화 일시 중지
235124
235113
 
235125
235114
  let langExtension;
235126
235115
  switch(language) {
@@ -235135,6 +235124,7 @@ class IdeDiff extends HTMLElement {
235135
235124
  const { asisEffect, tobeEffect } = this.#applyDiffDecorations(src1, src2);
235136
235125
 
235137
235126
  // 1단계: 텍스트 내용 변경과 언어 확장을 먼저 디스패치합니다.
235127
+ // 'to' 값을 현재 문서 길이 전체로 지정하여 정확한 교체를 보장합니다.
235138
235128
  this.#asisEditorView.dispatch({
235139
235129
  changes: { from: 0, to: this.#asisEditorView.state.doc.length, insert: src1 },
235140
235130
  effects: [
@@ -235149,10 +235139,9 @@ class IdeDiff extends HTMLElement {
235149
235139
  ]
235150
235140
  });
235151
235141
 
235152
- // 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화된 후,
235142
+ // ⭐️ 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화될 시간을 줍니다.
235153
235143
  // 다음 프레임에서 데코레이션 효과만 별도로 디스패치합니다.
235154
235144
  requestAnimationFrame(() => {
235155
- console.log(asisEffect, tobeEffect);
235156
235145
  this.#asisEditorView.dispatch({
235157
235146
  effects: [asisEffect]
235158
235147
  });
@@ -235160,8 +235149,8 @@ class IdeDiff extends HTMLElement {
235160
235149
  effects: [tobeEffect]
235161
235150
  });
235162
235151
 
235163
- // 3단계: 데코레이션까지 적용된 후 스크롤 동기화 활성화
235164
- // (필요하다면 여기도 requestAnimationFrame으로 더 지연시킬 수 있습니다.)
235152
+ // ⭐️ 3단계: 데코레이션까지 적용된 후 뷰가 다시 안정화될 시간을 한 번 더 줍니다.
235153
+ // 다음 프레임에서 스크롤 동기화를 활성화합니다.
235165
235154
  requestAnimationFrame(() => {
235166
235155
  this.#isScrollSyncActive = true;
235167
235156
  // 필요하다면 여기서 초기 스크롤 위치를 0으로 리셋하여 정렬을 보장할 수 있습니다.
@@ -1,6 +1,6 @@
1
1
  import ninegrid from "ninegrid2";
2
2
 
3
- // CodeMirror 6 핵심 및 확장 임포트
3
+ // CodeMirror 6 핵심 및 확장 임포트 (변동 없음)
4
4
  import {
5
5
  EditorView, lineNumbers, highlightSpecialChars, drawSelection,
6
6
  dropCursor, keymap, highlightActiveLine, highlightActiveLineGutter,
@@ -21,10 +21,10 @@ import { indentOnInput, syntaxHighlighting, defaultHighlightStyle } from "@codem
21
21
  import { lintKeymap } from "@codemirror/lint";
22
22
  import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
23
23
 
24
- // Diff 로직을 위해 diff-match-patch 사용
24
+ // Diff 로직을 위해 diff-match-patch 사용 (변동 없음)
25
25
  import { diff_match_patch } from 'diff-match-patch';
26
26
 
27
- // Diff 데코레이션을 위한 StateField 정의 (asis 에디터용)
27
+ // Diff 데코레이션을 위한 StateField 정의 (변동 없음)
28
28
  const asisDiffDecorations = StateField.define({
29
29
  create() { return Decoration.none; },
30
30
  update(decorations, tr) {
@@ -38,7 +38,6 @@ const asisDiffDecorations = StateField.define({
38
38
  provide: f => EditorView.decorations.from(f)
39
39
  });
40
40
 
41
- // Diff 데코레이션을 위한 StateField 정의 (tobe 에디터용)
42
41
  const tobeDiffDecorations = StateField.define({
43
42
  create() { return Decoration.none; },
44
43
  update(decorations, tr) {
@@ -52,7 +51,6 @@ const tobeDiffDecorations = StateField.define({
52
51
  provide: f => EditorView.decorations.from(f)
53
52
  });
54
53
 
55
- // 데코레이션 업데이트를 위한 Effect (트랜잭션에 포함시켜 상태 변경 알림)
56
54
  const setAsisDecorationsEffect = StateEffect.define();
57
55
  const setTobeDecorationsEffect = StateEffect.define();
58
56
 
@@ -65,10 +63,9 @@ export class IdeDiff extends HTMLElement {
65
63
 
66
64
  #languageCompartment = new Compartment();
67
65
 
68
- // ⭐️ 스크롤 동기화 활성/비활성화 플래그 및 핸들러 참조
69
66
  #isScrollSyncActive = false;
70
- _asisScrollHandler = null; // 클래스 속성으로 선언하여 removeEventListener에서 참조 가능
71
- _tobeScrollHandler = null; // 클래스 속성으로 선언하여 removeEventListener에서 참조 가능
67
+ _asisScrollHandler = null;
68
+ _tobeScrollHandler = null;
72
69
 
73
70
 
74
71
  constructor() {
@@ -79,38 +76,35 @@ export class IdeDiff extends HTMLElement {
79
76
  connectedCallback() {
80
77
  this.shadowRoot.innerHTML = `
81
78
  <style>
82
- /* ninegrid CSS 및 필요한 기본 스타일 */
79
+ /* ninegrid CSS 및 필요한 기본 스타일 (변동 없음) */
83
80
  @import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/ideDiff.css";
84
81
  ${ninegrid.getCustomPath(this, "ideDiff.css")}
85
82
 
86
- /* CodeMirror를 위한 기본적인 Flexbox 레이아웃 */
83
+ /* CodeMirror를 위한 기본적인 Flexbox 레이아웃 (변동 없음) */
87
84
  .wrapper {
88
85
  display: flex;
89
86
  width: 100%;
90
- height: 100%; /* 부모의 높이를 채우도록 설정 */
91
- overflow: hidden; /* 내부 스크롤을 위해 overflow 처리 */
87
+ height: 100%;
88
+ overflow: hidden;
92
89
  }
93
90
  .panel {
94
- flex: 1; /* 패널들이 남은 공간을 채우도록 */
95
- overflow: hidden; /* CodeMirror EditorView 자체가 스크롤을 처리 */
96
- min-width: 0; /* Flexbox 아이템이 content 때문에 늘어나는 것을 방지 */
91
+ flex: 1;
92
+ overflow: hidden;
93
+ min-width: 0;
97
94
  }
98
95
  .cm-editor {
99
- height: 100%; /* EditorView가 부모 div의 높이를 채우도록 */
96
+ height: 100%;
100
97
  }
101
98
 
102
- /* Diff 시각화를 위한 CSS 클래스 */
103
- /* 전체 배경색 */
104
- .cm-inserted-line-bg { background-color: #e6ffe6; } /* 연한 녹색 */
105
- .cm-deleted-line-bg { background-color: #ffe6e6; } /* 연한 빨간색 */
106
-
107
- /* 인라인(단어/문자) 변경 강조 */
99
+ /* Diff 시각화를 위한 CSS 클래스 (변동 없음) */
100
+ .cm-inserted-line-bg { background-color: #e6ffe6; }
101
+ .cm-deleted-line-bg { background-color: #ffe6e6; }
108
102
  .cm-inserted-inline {
109
- background-color: #90ee90; /* 밝은 녹색 */
103
+ background-color: #90ee90;
110
104
  font-weight: bold;
111
105
  }
112
106
  .cm-deleted-inline {
113
- background-color: #ff9999; /* 밝은 빨간색 */
107
+ background-color: #ff9999;
114
108
  text-decoration: line-through;
115
109
  font-weight: bold;
116
110
  }
@@ -171,11 +165,10 @@ export class IdeDiff extends HTMLElement {
171
165
  EditorState.readOnly.of(true),
172
166
  this.#languageCompartment.of(javascript()),
173
167
  asisDiffDecorations,
174
- // ⭐️ 중요: 뷰가 DOM에 완전히 렌더링될 때까지 기다립니다.
168
+ // ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
175
169
  EditorView.updateListener.of((update) => {
176
- // 뷰의 DOM 내용이 비어있지 않고, 아직 초기 로드가 완료되지 않았다면
177
170
  if (update.view.contentDOM.firstChild && !update.view._initialAsisContentLoaded) {
178
- update.view._initialAsisContentLoaded = true; // 플래그 설정
171
+ update.view._initialAsisContentLoaded = true;
179
172
  console.log("CodeMirror ASIS view is ready for initial content.");
180
173
  }
181
174
  })
@@ -194,11 +187,10 @@ export class IdeDiff extends HTMLElement {
194
187
  EditorState.readOnly.of(true),
195
188
  this.#languageCompartment.of(javascript()),
196
189
  tobeDiffDecorations,
197
- // ⭐️ 중요: 뷰가 DOM에 완전히 렌더링될 때까지 기다립니다.
190
+ // ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
198
191
  EditorView.updateListener.of((update) => {
199
- // 뷰의 DOM 내용이 비어있지 않고, 아직 초기 로드가 완료되지 않았다면
200
192
  if (update.view.contentDOM.firstChild && !update.view._initialTobeContentLoaded) {
201
- update.view._initialTobeContentLoaded = true; // 플래그 설정
193
+ update.view._initialTobeContentLoaded = true;
202
194
  console.log("CodeMirror TOBE view is ready for initial content.");
203
195
  }
204
196
  })
@@ -207,14 +199,11 @@ export class IdeDiff extends HTMLElement {
207
199
  parent: this.#tobeEditorEl
208
200
  });
209
201
 
210
- // ⭐️ 초기 스크롤 동기화는 여기서 설정만 하고, initialize에서 활성화 제어
211
202
  this.#setupScrollSync();
212
203
  };
213
204
 
214
- // ⭐️ 스크롤 리스너를 제어할 수 있도록 플래그 및 클래스 메서드 사용
215
205
  #setupScrollSync = () => {
216
- // 기존 리스너가 있다면 제거 (중복 방지 및 disconnectedCallback에서 제거 용이)
217
- if (this._asisScrollHandler) { // 핸들러가 이미 할당되어 있다면
206
+ if (this._asisScrollHandler) {
218
207
  this.#asisEditorView.scrollDOM.removeEventListener('scroll', this._asisScrollHandler);
219
208
  this.#tobeEditorView.scrollDOM.removeEventListener('scroll', this._tobeScrollHandler);
220
209
  }
@@ -223,7 +212,7 @@ export class IdeDiff extends HTMLElement {
223
212
  let scrollingB = false;
224
213
 
225
214
  this._asisScrollHandler = () => {
226
- if (!this.#isScrollSyncActive) return; // 활성화되지 않았으면 스킵
215
+ if (!this.#isScrollSyncActive) return;
227
216
 
228
217
  if (!scrollingB) {
229
218
  scrollingA = true;
@@ -234,7 +223,7 @@ export class IdeDiff extends HTMLElement {
234
223
  };
235
224
 
236
225
  this._tobeScrollHandler = () => {
237
- if (!this.#isScrollSyncActive) return; // 활성화되지 않았으면 스킵
226
+ if (!this.#isScrollSyncActive) return;
238
227
 
239
228
  if (!scrollingA) {
240
229
  scrollingB = true;
@@ -248,7 +237,6 @@ export class IdeDiff extends HTMLElement {
248
237
  this.#tobeEditorView.scrollDOM.addEventListener('scroll', this._tobeScrollHandler);
249
238
  };
250
239
 
251
- // #applyDiffDecorations 함수 (이전 수정본과 동일, Text.of 사용)
252
240
  #applyDiffDecorations = (asisSrc, tobeSrc) => {
253
241
  const dmp = new diff_match_patch();
254
242
  const diffs = dmp.diff_main(asisSrc, tobeSrc);
@@ -262,6 +250,8 @@ export class IdeDiff extends HTMLElement {
262
250
  let asisCursor = 0;
263
251
  let tobeCursor = 0;
264
252
 
253
+ // ⭐️ 중요: 새로운 문서 내용을 기반으로 임시 Doc 객체를 생성합니다.
254
+ // 이 Doc 객체를 사용하여 lineAt()을 호출합니다.
265
255
  const asisDoc = Text.of(asisSrc.split('\n'));
266
256
  const tobeDoc = Text.of(tobeSrc.split('\n'));
267
257
 
@@ -371,8 +361,7 @@ export class IdeDiff extends HTMLElement {
371
361
  return;
372
362
  }
373
363
 
374
- // 초기화 시작 스크롤 동기화 일시 중지
375
- this.#isScrollSyncActive = false;
364
+ this.#isScrollSyncActive = false; // 스크롤 동기화 일시 중지
376
365
 
377
366
  let langExtension;
378
367
  switch(language) {
@@ -387,6 +376,7 @@ export class IdeDiff extends HTMLElement {
387
376
  const { asisEffect, tobeEffect } = this.#applyDiffDecorations(src1, src2);
388
377
 
389
378
  // 1단계: 텍스트 내용 변경과 언어 확장을 먼저 디스패치합니다.
379
+ // 'to' 값을 현재 문서 길이 전체로 지정하여 정확한 교체를 보장합니다.
390
380
  this.#asisEditorView.dispatch({
391
381
  changes: { from: 0, to: this.#asisEditorView.state.doc.length, insert: src1 },
392
382
  effects: [
@@ -401,10 +391,9 @@ export class IdeDiff extends HTMLElement {
401
391
  ]
402
392
  });
403
393
 
404
- // 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화된 후,
394
+ // ⭐️ 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화될 시간을 줍니다.
405
395
  // 다음 프레임에서 데코레이션 효과만 별도로 디스패치합니다.
406
396
  requestAnimationFrame(() => {
407
- console.log(asisEffect, tobeEffect);
408
397
  this.#asisEditorView.dispatch({
409
398
  effects: [asisEffect]
410
399
  });
@@ -412,8 +401,8 @@ export class IdeDiff extends HTMLElement {
412
401
  effects: [tobeEffect]
413
402
  });
414
403
 
415
- // 3단계: 데코레이션까지 적용된 후 스크롤 동기화 활성화
416
- // (필요하다면 여기도 requestAnimationFrame으로 더 지연시킬 수 있습니다.)
404
+ // ⭐️ 3단계: 데코레이션까지 적용된 후 뷰가 다시 안정화될 시간을 한 번 더 줍니다.
405
+ // 다음 프레임에서 스크롤 동기화를 활성화합니다.
417
406
  requestAnimationFrame(() => {
418
407
  this.#isScrollSyncActive = true;
419
408
  // 필요하다면 여기서 초기 스크롤 위치를 0으로 리셋하여 정렬을 보장할 수 있습니다.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ide-assi",
3
3
  "type": "module",
4
- "version": "0.371.0",
4
+ "version": "0.373.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
@@ -1,6 +1,6 @@
1
1
  import ninegrid from "ninegrid2";
2
2
 
3
- // CodeMirror 6 핵심 및 확장 임포트
3
+ // CodeMirror 6 핵심 및 확장 임포트 (변동 없음)
4
4
  import {
5
5
  EditorView, lineNumbers, highlightSpecialChars, drawSelection,
6
6
  dropCursor, keymap, highlightActiveLine, highlightActiveLineGutter,
@@ -21,10 +21,10 @@ import { indentOnInput, syntaxHighlighting, defaultHighlightStyle } from "@codem
21
21
  import { lintKeymap } from "@codemirror/lint";
22
22
  import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
23
23
 
24
- // Diff 로직을 위해 diff-match-patch 사용
24
+ // Diff 로직을 위해 diff-match-patch 사용 (변동 없음)
25
25
  import { diff_match_patch } from 'diff-match-patch';
26
26
 
27
- // Diff 데코레이션을 위한 StateField 정의 (asis 에디터용)
27
+ // Diff 데코레이션을 위한 StateField 정의 (변동 없음)
28
28
  const asisDiffDecorations = StateField.define({
29
29
  create() { return Decoration.none; },
30
30
  update(decorations, tr) {
@@ -38,7 +38,6 @@ const asisDiffDecorations = StateField.define({
38
38
  provide: f => EditorView.decorations.from(f)
39
39
  });
40
40
 
41
- // Diff 데코레이션을 위한 StateField 정의 (tobe 에디터용)
42
41
  const tobeDiffDecorations = StateField.define({
43
42
  create() { return Decoration.none; },
44
43
  update(decorations, tr) {
@@ -52,7 +51,6 @@ const tobeDiffDecorations = StateField.define({
52
51
  provide: f => EditorView.decorations.from(f)
53
52
  });
54
53
 
55
- // 데코레이션 업데이트를 위한 Effect (트랜잭션에 포함시켜 상태 변경 알림)
56
54
  const setAsisDecorationsEffect = StateEffect.define();
57
55
  const setTobeDecorationsEffect = StateEffect.define();
58
56
 
@@ -65,10 +63,9 @@ export class IdeDiff extends HTMLElement {
65
63
 
66
64
  #languageCompartment = new Compartment();
67
65
 
68
- // ⭐️ 스크롤 동기화 활성/비활성화 플래그 및 핸들러 참조
69
66
  #isScrollSyncActive = false;
70
- _asisScrollHandler = null; // 클래스 속성으로 선언하여 removeEventListener에서 참조 가능
71
- _tobeScrollHandler = null; // 클래스 속성으로 선언하여 removeEventListener에서 참조 가능
67
+ _asisScrollHandler = null;
68
+ _tobeScrollHandler = null;
72
69
 
73
70
 
74
71
  constructor() {
@@ -79,38 +76,35 @@ export class IdeDiff extends HTMLElement {
79
76
  connectedCallback() {
80
77
  this.shadowRoot.innerHTML = `
81
78
  <style>
82
- /* ninegrid CSS 및 필요한 기본 스타일 */
79
+ /* ninegrid CSS 및 필요한 기본 스타일 (변동 없음) */
83
80
  @import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/ideDiff.css";
84
81
  ${ninegrid.getCustomPath(this, "ideDiff.css")}
85
82
 
86
- /* CodeMirror를 위한 기본적인 Flexbox 레이아웃 */
83
+ /* CodeMirror를 위한 기본적인 Flexbox 레이아웃 (변동 없음) */
87
84
  .wrapper {
88
85
  display: flex;
89
86
  width: 100%;
90
- height: 100%; /* 부모의 높이를 채우도록 설정 */
91
- overflow: hidden; /* 내부 스크롤을 위해 overflow 처리 */
87
+ height: 100%;
88
+ overflow: hidden;
92
89
  }
93
90
  .panel {
94
- flex: 1; /* 패널들이 남은 공간을 채우도록 */
95
- overflow: hidden; /* CodeMirror EditorView 자체가 스크롤을 처리 */
96
- min-width: 0; /* Flexbox 아이템이 content 때문에 늘어나는 것을 방지 */
91
+ flex: 1;
92
+ overflow: hidden;
93
+ min-width: 0;
97
94
  }
98
95
  .cm-editor {
99
- height: 100%; /* EditorView가 부모 div의 높이를 채우도록 */
96
+ height: 100%;
100
97
  }
101
98
 
102
- /* Diff 시각화를 위한 CSS 클래스 */
103
- /* 전체 배경색 */
104
- .cm-inserted-line-bg { background-color: #e6ffe6; } /* 연한 녹색 */
105
- .cm-deleted-line-bg { background-color: #ffe6e6; } /* 연한 빨간색 */
106
-
107
- /* 인라인(단어/문자) 변경 강조 */
99
+ /* Diff 시각화를 위한 CSS 클래스 (변동 없음) */
100
+ .cm-inserted-line-bg { background-color: #e6ffe6; }
101
+ .cm-deleted-line-bg { background-color: #ffe6e6; }
108
102
  .cm-inserted-inline {
109
- background-color: #90ee90; /* 밝은 녹색 */
103
+ background-color: #90ee90;
110
104
  font-weight: bold;
111
105
  }
112
106
  .cm-deleted-inline {
113
- background-color: #ff9999; /* 밝은 빨간색 */
107
+ background-color: #ff9999;
114
108
  text-decoration: line-through;
115
109
  font-weight: bold;
116
110
  }
@@ -171,11 +165,10 @@ export class IdeDiff extends HTMLElement {
171
165
  EditorState.readOnly.of(true),
172
166
  this.#languageCompartment.of(javascript()),
173
167
  asisDiffDecorations,
174
- // ⭐️ 중요: 뷰가 DOM에 완전히 렌더링될 때까지 기다립니다.
168
+ // ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
175
169
  EditorView.updateListener.of((update) => {
176
- // 뷰의 DOM 내용이 비어있지 않고, 아직 초기 로드가 완료되지 않았다면
177
170
  if (update.view.contentDOM.firstChild && !update.view._initialAsisContentLoaded) {
178
- update.view._initialAsisContentLoaded = true; // 플래그 설정
171
+ update.view._initialAsisContentLoaded = true;
179
172
  console.log("CodeMirror ASIS view is ready for initial content.");
180
173
  }
181
174
  })
@@ -194,11 +187,10 @@ export class IdeDiff extends HTMLElement {
194
187
  EditorState.readOnly.of(true),
195
188
  this.#languageCompartment.of(javascript()),
196
189
  tobeDiffDecorations,
197
- // ⭐️ 중요: 뷰가 DOM에 완전히 렌더링될 때까지 기다립니다.
190
+ // ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
198
191
  EditorView.updateListener.of((update) => {
199
- // 뷰의 DOM 내용이 비어있지 않고, 아직 초기 로드가 완료되지 않았다면
200
192
  if (update.view.contentDOM.firstChild && !update.view._initialTobeContentLoaded) {
201
- update.view._initialTobeContentLoaded = true; // 플래그 설정
193
+ update.view._initialTobeContentLoaded = true;
202
194
  console.log("CodeMirror TOBE view is ready for initial content.");
203
195
  }
204
196
  })
@@ -207,14 +199,11 @@ export class IdeDiff extends HTMLElement {
207
199
  parent: this.#tobeEditorEl
208
200
  });
209
201
 
210
- // ⭐️ 초기 스크롤 동기화는 여기서 설정만 하고, initialize에서 활성화 제어
211
202
  this.#setupScrollSync();
212
203
  };
213
204
 
214
- // ⭐️ 스크롤 리스너를 제어할 수 있도록 플래그 및 클래스 메서드 사용
215
205
  #setupScrollSync = () => {
216
- // 기존 리스너가 있다면 제거 (중복 방지 및 disconnectedCallback에서 제거 용이)
217
- if (this._asisScrollHandler) { // 핸들러가 이미 할당되어 있다면
206
+ if (this._asisScrollHandler) {
218
207
  this.#asisEditorView.scrollDOM.removeEventListener('scroll', this._asisScrollHandler);
219
208
  this.#tobeEditorView.scrollDOM.removeEventListener('scroll', this._tobeScrollHandler);
220
209
  }
@@ -223,7 +212,7 @@ export class IdeDiff extends HTMLElement {
223
212
  let scrollingB = false;
224
213
 
225
214
  this._asisScrollHandler = () => {
226
- if (!this.#isScrollSyncActive) return; // 활성화되지 않았으면 스킵
215
+ if (!this.#isScrollSyncActive) return;
227
216
 
228
217
  if (!scrollingB) {
229
218
  scrollingA = true;
@@ -234,7 +223,7 @@ export class IdeDiff extends HTMLElement {
234
223
  };
235
224
 
236
225
  this._tobeScrollHandler = () => {
237
- if (!this.#isScrollSyncActive) return; // 활성화되지 않았으면 스킵
226
+ if (!this.#isScrollSyncActive) return;
238
227
 
239
228
  if (!scrollingA) {
240
229
  scrollingB = true;
@@ -248,7 +237,6 @@ export class IdeDiff extends HTMLElement {
248
237
  this.#tobeEditorView.scrollDOM.addEventListener('scroll', this._tobeScrollHandler);
249
238
  };
250
239
 
251
- // #applyDiffDecorations 함수 (이전 수정본과 동일, Text.of 사용)
252
240
  #applyDiffDecorations = (asisSrc, tobeSrc) => {
253
241
  const dmp = new diff_match_patch();
254
242
  const diffs = dmp.diff_main(asisSrc, tobeSrc);
@@ -262,6 +250,8 @@ export class IdeDiff extends HTMLElement {
262
250
  let asisCursor = 0;
263
251
  let tobeCursor = 0;
264
252
 
253
+ // ⭐️ 중요: 새로운 문서 내용을 기반으로 임시 Doc 객체를 생성합니다.
254
+ // 이 Doc 객체를 사용하여 lineAt()을 호출합니다.
265
255
  const asisDoc = Text.of(asisSrc.split('\n'));
266
256
  const tobeDoc = Text.of(tobeSrc.split('\n'));
267
257
 
@@ -371,8 +361,7 @@ export class IdeDiff extends HTMLElement {
371
361
  return;
372
362
  }
373
363
 
374
- // 초기화 시작 스크롤 동기화 일시 중지
375
- this.#isScrollSyncActive = false;
364
+ this.#isScrollSyncActive = false; // 스크롤 동기화 일시 중지
376
365
 
377
366
  let langExtension;
378
367
  switch(language) {
@@ -387,6 +376,7 @@ export class IdeDiff extends HTMLElement {
387
376
  const { asisEffect, tobeEffect } = this.#applyDiffDecorations(src1, src2);
388
377
 
389
378
  // 1단계: 텍스트 내용 변경과 언어 확장을 먼저 디스패치합니다.
379
+ // 'to' 값을 현재 문서 길이 전체로 지정하여 정확한 교체를 보장합니다.
390
380
  this.#asisEditorView.dispatch({
391
381
  changes: { from: 0, to: this.#asisEditorView.state.doc.length, insert: src1 },
392
382
  effects: [
@@ -401,10 +391,9 @@ export class IdeDiff extends HTMLElement {
401
391
  ]
402
392
  });
403
393
 
404
- // 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화된 후,
394
+ // ⭐️ 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화될 시간을 줍니다.
405
395
  // 다음 프레임에서 데코레이션 효과만 별도로 디스패치합니다.
406
396
  requestAnimationFrame(() => {
407
- console.log(asisEffect, tobeEffect);
408
397
  this.#asisEditorView.dispatch({
409
398
  effects: [asisEffect]
410
399
  });
@@ -412,8 +401,8 @@ export class IdeDiff extends HTMLElement {
412
401
  effects: [tobeEffect]
413
402
  });
414
403
 
415
- // 3단계: 데코레이션까지 적용된 후 스크롤 동기화 활성화
416
- // (필요하다면 여기도 requestAnimationFrame으로 더 지연시킬 수 있습니다.)
404
+ // ⭐️ 3단계: 데코레이션까지 적용된 후 뷰가 다시 안정화될 시간을 한 번 더 줍니다.
405
+ // 다음 프레임에서 스크롤 동기화를 활성화합니다.
417
406
  requestAnimationFrame(() => {
418
407
  this.#isScrollSyncActive = true;
419
408
  // 필요하다면 여기서 초기 스크롤 위치를 0으로 리셋하여 정렬을 보장할 수 있습니다.