ide-assi 0.343.0 → 0.345.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.
- package/dist/bundle.cjs.js +74 -44
- package/dist/bundle.esm.js +74 -44
- package/dist/components/ideDiff.js +74 -44
- package/package.json +1 -1
- package/src/components/ideDiff.js +74 -44
package/dist/bundle.cjs.js
CHANGED
|
@@ -234948,96 +234948,126 @@ class IdeDiff extends HTMLElement {
|
|
|
234948
234948
|
const diffs = dmp.diff_main(asisSrc, tobeSrc);
|
|
234949
234949
|
dmp.diff_cleanupSemantic(diffs);
|
|
234950
234950
|
|
|
234951
|
-
|
|
234952
|
-
const
|
|
234953
|
-
const
|
|
234951
|
+
const asisLineDecos = [];
|
|
234952
|
+
const asisMarkDecos = [];
|
|
234953
|
+
const tobeLineDecos = [];
|
|
234954
|
+
const tobeMarkDecos = [];
|
|
234954
234955
|
|
|
234955
|
-
let asisCursor = 0;
|
|
234956
|
-
let tobeCursor = 0;
|
|
234956
|
+
let asisCursor = 0;
|
|
234957
|
+
let tobeCursor = 0;
|
|
234957
234958
|
|
|
234958
234959
|
for (const [op, text] of diffs) {
|
|
234959
234960
|
const len = text.length;
|
|
234960
234961
|
|
|
234961
234962
|
switch (op) {
|
|
234962
|
-
case diffMatchPatchExports.diff_match_patch.DIFF_INSERT: //
|
|
234963
|
-
|
|
234964
|
-
tobeDecorationsToAdd.push({
|
|
234963
|
+
case diffMatchPatchExports.diff_match_patch.DIFF_INSERT: // Added text
|
|
234964
|
+
tobeMarkDecos.push({
|
|
234965
234965
|
from: tobeCursor,
|
|
234966
234966
|
to: tobeCursor + len,
|
|
234967
234967
|
deco: Decoration.mark({ class: "cm-inserted-inline" })
|
|
234968
234968
|
});
|
|
234969
234969
|
|
|
234970
|
-
// tobe 쪽에 줄 배경 데코레이션 추가 (삽입된 줄)
|
|
234971
|
-
// text가 여러 줄일 수 있으므로 각 줄에 적용
|
|
234972
234970
|
let currentTobeLineOffset = tobeCursor;
|
|
234973
234971
|
const tobeLines = text.split('\n');
|
|
234974
234972
|
for (let i = 0; i < tobeLines.length; i++) {
|
|
234975
|
-
//
|
|
234976
|
-
|
|
234977
|
-
|
|
234978
|
-
|
|
234979
|
-
|
|
234980
|
-
|
|
234981
|
-
|
|
234982
|
-
|
|
234983
|
-
|
|
234973
|
+
// ⭐️ 중요: lineAt() 호출 전에 유효한 문서 범위 내에 있는지 확인
|
|
234974
|
+
if (currentTobeLineOffset < this.#tobeEditorView.state.doc.length) {
|
|
234975
|
+
const line = this.#tobeEditorView.state.doc.lineAt(currentTobeLineOffset);
|
|
234976
|
+
tobeLineDecos.push({
|
|
234977
|
+
from: line.from,
|
|
234978
|
+
to: line.to,
|
|
234979
|
+
deco: Decoration.line({ class: "cm-inserted-line-bg" })
|
|
234980
|
+
});
|
|
234981
|
+
}
|
|
234982
|
+
// 다음 줄의 시작 위치 계산. 마지막 줄이 아니면 +1 (개행문자)
|
|
234983
|
+
currentTobeLineOffset += tobeLines[i].length + (i < tobeLines.length -1 ? 1 : 0);
|
|
234984
|
+
// 만약 마지막 줄이 비어있다면, 더 이상 진행하지 않도록 방지
|
|
234985
|
+
if (i === tobeLines.length - 1 && tobeLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
234986
|
+
// 마지막 줄이 빈 줄이고 텍스트가 개행으로 끝나지 않으면 (오프셋이 더 이상 증가할 필요 없음)
|
|
234987
|
+
break;
|
|
234988
|
+
}
|
|
234984
234989
|
}
|
|
234985
234990
|
|
|
234986
234991
|
tobeCursor += len;
|
|
234987
234992
|
break;
|
|
234988
234993
|
|
|
234989
|
-
case diffMatchPatchExports.diff_match_patch.DIFF_DELETE: //
|
|
234990
|
-
|
|
234991
|
-
asisDecorationsToAdd.push({
|
|
234994
|
+
case diffMatchPatchExports.diff_match_patch.DIFF_DELETE: // Deleted text
|
|
234995
|
+
asisMarkDecos.push({
|
|
234992
234996
|
from: asisCursor,
|
|
234993
234997
|
to: asisCursor + len,
|
|
234994
234998
|
deco: Decoration.mark({ class: "cm-deleted-inline" })
|
|
234995
234999
|
});
|
|
234996
235000
|
|
|
234997
|
-
// asis 쪽에 줄 배경 데코레이션 추가 (삭제된 줄)
|
|
234998
235001
|
let currentAsisLineOffset = asisCursor;
|
|
234999
235002
|
const asisLines = text.split('\n');
|
|
235000
235003
|
for (let i = 0; i < asisLines.length; i++) {
|
|
235001
|
-
|
|
235002
|
-
|
|
235003
|
-
|
|
235004
|
-
|
|
235005
|
-
|
|
235006
|
-
|
|
235007
|
-
|
|
235004
|
+
// ⭐️ 중요: lineAt() 호출 전에 유효한 문서 범위 내에 있는지 확인
|
|
235005
|
+
if (currentAsisLineOffset < this.#asisEditorView.state.doc.length) {
|
|
235006
|
+
const line = this.#asisEditorView.state.doc.lineAt(currentAsisLineOffset);
|
|
235007
|
+
asisLineDecos.push({
|
|
235008
|
+
from: line.from,
|
|
235009
|
+
to: line.to,
|
|
235010
|
+
deco: Decoration.line({ class: "cm-deleted-line-bg" })
|
|
235011
|
+
});
|
|
235012
|
+
}
|
|
235013
|
+
currentAsisLineOffset += asisLines[i].length + (i < asisLines.length -1 ? 1 : 0);
|
|
235014
|
+
if (i === asisLines.length - 1 && asisLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
235015
|
+
break;
|
|
235016
|
+
}
|
|
235008
235017
|
}
|
|
235009
235018
|
|
|
235010
235019
|
asisCursor += len;
|
|
235011
235020
|
break;
|
|
235012
235021
|
|
|
235013
|
-
case diffMatchPatchExports.diff_match_patch.DIFF_EQUAL: //
|
|
235022
|
+
case diffMatchPatchExports.diff_match_patch.DIFF_EQUAL: // Unchanged text
|
|
235014
235023
|
asisCursor += len;
|
|
235015
235024
|
tobeCursor += len;
|
|
235016
235025
|
break;
|
|
235017
235026
|
}
|
|
235018
235027
|
}
|
|
235019
235028
|
|
|
235020
|
-
//
|
|
235021
|
-
|
|
235022
|
-
|
|
235029
|
+
// Sort all collections by 'from' position (항상 좋은 습관)
|
|
235030
|
+
asisLineDecos.sort((a, b) => a.from - b.from);
|
|
235031
|
+
asisMarkDecos.sort((a, b) => a.from - b.from);
|
|
235032
|
+
tobeLineDecos.sort((a, b) => a.from - b.from);
|
|
235033
|
+
tobeMarkDecos.sort((a, b) => a.from - b.from);
|
|
235023
235034
|
|
|
235024
|
-
//
|
|
235025
|
-
const
|
|
235026
|
-
for (const { from, to, deco } of
|
|
235027
|
-
|
|
235035
|
+
// ASIS 에디터용 줄 및 마크 데코레이션을 위한 별도 RangeSetBuilder 생성
|
|
235036
|
+
const asisLineBuilder = new RangeSetBuilder();
|
|
235037
|
+
for (const { from, to, deco } of asisLineDecos) {
|
|
235038
|
+
asisLineBuilder.add(from, to, deco);
|
|
235028
235039
|
}
|
|
235040
|
+
const asisMarkBuilder = new RangeSetBuilder();
|
|
235041
|
+
for (const { from, to, deco } of asisMarkDecos) {
|
|
235042
|
+
asisMarkBuilder.add(from, to, deco);
|
|
235043
|
+
}
|
|
235044
|
+
|
|
235045
|
+
// ASIS 에디터용 줄 및 마크 RangeSet 결합
|
|
235046
|
+
const finalAsisDecorations = asisLineBuilder.finish().update({
|
|
235047
|
+
add: asisMarkBuilder.finish().children
|
|
235048
|
+
});
|
|
235029
235049
|
|
|
235030
|
-
|
|
235031
|
-
|
|
235032
|
-
|
|
235050
|
+
// TOBE 에디터용 줄 및 마크 데코레이션을 위한 별도 RangeSetBuilder 생성
|
|
235051
|
+
const tobeLineBuilder = new RangeSetBuilder();
|
|
235052
|
+
for (const { from, to, deco } of tobeLineDecos) {
|
|
235053
|
+
tobeLineBuilder.add(from, to, deco);
|
|
235054
|
+
}
|
|
235055
|
+
const tobeMarkBuilder = new RangeSetBuilder();
|
|
235056
|
+
for (const { from, to, deco } of tobeMarkDecos) {
|
|
235057
|
+
tobeMarkBuilder.add(from, to, deco);
|
|
235033
235058
|
}
|
|
235034
235059
|
|
|
235035
|
-
//
|
|
235060
|
+
// TOBE 에디터용 줄 및 마크 RangeSet 결합
|
|
235061
|
+
const finalTobeDecorations = tobeLineBuilder.finish().update({
|
|
235062
|
+
add: tobeMarkBuilder.finish().children
|
|
235063
|
+
});
|
|
235064
|
+
|
|
235065
|
+
// 데코레이션 업데이트를 위한 Effect 디스패치
|
|
235036
235066
|
this.#asisEditorView.dispatch({
|
|
235037
|
-
effects: setAsisDecorationsEffect.of(
|
|
235067
|
+
effects: setAsisDecorationsEffect.of(finalAsisDecorations)
|
|
235038
235068
|
});
|
|
235039
235069
|
this.#tobeEditorView.dispatch({
|
|
235040
|
-
effects: setTobeDecorationsEffect.of(
|
|
235070
|
+
effects: setTobeDecorationsEffect.of(finalTobeDecorations)
|
|
235041
235071
|
});
|
|
235042
235072
|
};
|
|
235043
235073
|
|
package/dist/bundle.esm.js
CHANGED
|
@@ -234944,96 +234944,126 @@ class IdeDiff extends HTMLElement {
|
|
|
234944
234944
|
const diffs = dmp.diff_main(asisSrc, tobeSrc);
|
|
234945
234945
|
dmp.diff_cleanupSemantic(diffs);
|
|
234946
234946
|
|
|
234947
|
-
|
|
234948
|
-
const
|
|
234949
|
-
const
|
|
234947
|
+
const asisLineDecos = [];
|
|
234948
|
+
const asisMarkDecos = [];
|
|
234949
|
+
const tobeLineDecos = [];
|
|
234950
|
+
const tobeMarkDecos = [];
|
|
234950
234951
|
|
|
234951
|
-
let asisCursor = 0;
|
|
234952
|
-
let tobeCursor = 0;
|
|
234952
|
+
let asisCursor = 0;
|
|
234953
|
+
let tobeCursor = 0;
|
|
234953
234954
|
|
|
234954
234955
|
for (const [op, text] of diffs) {
|
|
234955
234956
|
const len = text.length;
|
|
234956
234957
|
|
|
234957
234958
|
switch (op) {
|
|
234958
|
-
case diffMatchPatchExports.diff_match_patch.DIFF_INSERT: //
|
|
234959
|
-
|
|
234960
|
-
tobeDecorationsToAdd.push({
|
|
234959
|
+
case diffMatchPatchExports.diff_match_patch.DIFF_INSERT: // Added text
|
|
234960
|
+
tobeMarkDecos.push({
|
|
234961
234961
|
from: tobeCursor,
|
|
234962
234962
|
to: tobeCursor + len,
|
|
234963
234963
|
deco: Decoration.mark({ class: "cm-inserted-inline" })
|
|
234964
234964
|
});
|
|
234965
234965
|
|
|
234966
|
-
// tobe 쪽에 줄 배경 데코레이션 추가 (삽입된 줄)
|
|
234967
|
-
// text가 여러 줄일 수 있으므로 각 줄에 적용
|
|
234968
234966
|
let currentTobeLineOffset = tobeCursor;
|
|
234969
234967
|
const tobeLines = text.split('\n');
|
|
234970
234968
|
for (let i = 0; i < tobeLines.length; i++) {
|
|
234971
|
-
//
|
|
234972
|
-
|
|
234973
|
-
|
|
234974
|
-
|
|
234975
|
-
|
|
234976
|
-
|
|
234977
|
-
|
|
234978
|
-
|
|
234979
|
-
|
|
234969
|
+
// ⭐️ 중요: lineAt() 호출 전에 유효한 문서 범위 내에 있는지 확인
|
|
234970
|
+
if (currentTobeLineOffset < this.#tobeEditorView.state.doc.length) {
|
|
234971
|
+
const line = this.#tobeEditorView.state.doc.lineAt(currentTobeLineOffset);
|
|
234972
|
+
tobeLineDecos.push({
|
|
234973
|
+
from: line.from,
|
|
234974
|
+
to: line.to,
|
|
234975
|
+
deco: Decoration.line({ class: "cm-inserted-line-bg" })
|
|
234976
|
+
});
|
|
234977
|
+
}
|
|
234978
|
+
// 다음 줄의 시작 위치 계산. 마지막 줄이 아니면 +1 (개행문자)
|
|
234979
|
+
currentTobeLineOffset += tobeLines[i].length + (i < tobeLines.length -1 ? 1 : 0);
|
|
234980
|
+
// 만약 마지막 줄이 비어있다면, 더 이상 진행하지 않도록 방지
|
|
234981
|
+
if (i === tobeLines.length - 1 && tobeLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
234982
|
+
// 마지막 줄이 빈 줄이고 텍스트가 개행으로 끝나지 않으면 (오프셋이 더 이상 증가할 필요 없음)
|
|
234983
|
+
break;
|
|
234984
|
+
}
|
|
234980
234985
|
}
|
|
234981
234986
|
|
|
234982
234987
|
tobeCursor += len;
|
|
234983
234988
|
break;
|
|
234984
234989
|
|
|
234985
|
-
case diffMatchPatchExports.diff_match_patch.DIFF_DELETE: //
|
|
234986
|
-
|
|
234987
|
-
asisDecorationsToAdd.push({
|
|
234990
|
+
case diffMatchPatchExports.diff_match_patch.DIFF_DELETE: // Deleted text
|
|
234991
|
+
asisMarkDecos.push({
|
|
234988
234992
|
from: asisCursor,
|
|
234989
234993
|
to: asisCursor + len,
|
|
234990
234994
|
deco: Decoration.mark({ class: "cm-deleted-inline" })
|
|
234991
234995
|
});
|
|
234992
234996
|
|
|
234993
|
-
// asis 쪽에 줄 배경 데코레이션 추가 (삭제된 줄)
|
|
234994
234997
|
let currentAsisLineOffset = asisCursor;
|
|
234995
234998
|
const asisLines = text.split('\n');
|
|
234996
234999
|
for (let i = 0; i < asisLines.length; i++) {
|
|
234997
|
-
|
|
234998
|
-
|
|
234999
|
-
|
|
235000
|
-
|
|
235001
|
-
|
|
235002
|
-
|
|
235003
|
-
|
|
235000
|
+
// ⭐️ 중요: lineAt() 호출 전에 유효한 문서 범위 내에 있는지 확인
|
|
235001
|
+
if (currentAsisLineOffset < this.#asisEditorView.state.doc.length) {
|
|
235002
|
+
const line = this.#asisEditorView.state.doc.lineAt(currentAsisLineOffset);
|
|
235003
|
+
asisLineDecos.push({
|
|
235004
|
+
from: line.from,
|
|
235005
|
+
to: line.to,
|
|
235006
|
+
deco: Decoration.line({ class: "cm-deleted-line-bg" })
|
|
235007
|
+
});
|
|
235008
|
+
}
|
|
235009
|
+
currentAsisLineOffset += asisLines[i].length + (i < asisLines.length -1 ? 1 : 0);
|
|
235010
|
+
if (i === asisLines.length - 1 && asisLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
235011
|
+
break;
|
|
235012
|
+
}
|
|
235004
235013
|
}
|
|
235005
235014
|
|
|
235006
235015
|
asisCursor += len;
|
|
235007
235016
|
break;
|
|
235008
235017
|
|
|
235009
|
-
case diffMatchPatchExports.diff_match_patch.DIFF_EQUAL: //
|
|
235018
|
+
case diffMatchPatchExports.diff_match_patch.DIFF_EQUAL: // Unchanged text
|
|
235010
235019
|
asisCursor += len;
|
|
235011
235020
|
tobeCursor += len;
|
|
235012
235021
|
break;
|
|
235013
235022
|
}
|
|
235014
235023
|
}
|
|
235015
235024
|
|
|
235016
|
-
//
|
|
235017
|
-
|
|
235018
|
-
|
|
235025
|
+
// Sort all collections by 'from' position (항상 좋은 습관)
|
|
235026
|
+
asisLineDecos.sort((a, b) => a.from - b.from);
|
|
235027
|
+
asisMarkDecos.sort((a, b) => a.from - b.from);
|
|
235028
|
+
tobeLineDecos.sort((a, b) => a.from - b.from);
|
|
235029
|
+
tobeMarkDecos.sort((a, b) => a.from - b.from);
|
|
235019
235030
|
|
|
235020
|
-
//
|
|
235021
|
-
const
|
|
235022
|
-
for (const { from, to, deco } of
|
|
235023
|
-
|
|
235031
|
+
// ASIS 에디터용 줄 및 마크 데코레이션을 위한 별도 RangeSetBuilder 생성
|
|
235032
|
+
const asisLineBuilder = new RangeSetBuilder();
|
|
235033
|
+
for (const { from, to, deco } of asisLineDecos) {
|
|
235034
|
+
asisLineBuilder.add(from, to, deco);
|
|
235024
235035
|
}
|
|
235036
|
+
const asisMarkBuilder = new RangeSetBuilder();
|
|
235037
|
+
for (const { from, to, deco } of asisMarkDecos) {
|
|
235038
|
+
asisMarkBuilder.add(from, to, deco);
|
|
235039
|
+
}
|
|
235040
|
+
|
|
235041
|
+
// ASIS 에디터용 줄 및 마크 RangeSet 결합
|
|
235042
|
+
const finalAsisDecorations = asisLineBuilder.finish().update({
|
|
235043
|
+
add: asisMarkBuilder.finish().children
|
|
235044
|
+
});
|
|
235025
235045
|
|
|
235026
|
-
|
|
235027
|
-
|
|
235028
|
-
|
|
235046
|
+
// TOBE 에디터용 줄 및 마크 데코레이션을 위한 별도 RangeSetBuilder 생성
|
|
235047
|
+
const tobeLineBuilder = new RangeSetBuilder();
|
|
235048
|
+
for (const { from, to, deco } of tobeLineDecos) {
|
|
235049
|
+
tobeLineBuilder.add(from, to, deco);
|
|
235050
|
+
}
|
|
235051
|
+
const tobeMarkBuilder = new RangeSetBuilder();
|
|
235052
|
+
for (const { from, to, deco } of tobeMarkDecos) {
|
|
235053
|
+
tobeMarkBuilder.add(from, to, deco);
|
|
235029
235054
|
}
|
|
235030
235055
|
|
|
235031
|
-
//
|
|
235056
|
+
// TOBE 에디터용 줄 및 마크 RangeSet 결합
|
|
235057
|
+
const finalTobeDecorations = tobeLineBuilder.finish().update({
|
|
235058
|
+
add: tobeMarkBuilder.finish().children
|
|
235059
|
+
});
|
|
235060
|
+
|
|
235061
|
+
// 데코레이션 업데이트를 위한 Effect 디스패치
|
|
235032
235062
|
this.#asisEditorView.dispatch({
|
|
235033
|
-
effects: setAsisDecorationsEffect.of(
|
|
235063
|
+
effects: setAsisDecorationsEffect.of(finalAsisDecorations)
|
|
235034
235064
|
});
|
|
235035
235065
|
this.#tobeEditorView.dispatch({
|
|
235036
|
-
effects: setTobeDecorationsEffect.of(
|
|
235066
|
+
effects: setTobeDecorationsEffect.of(finalTobeDecorations)
|
|
235037
235067
|
});
|
|
235038
235068
|
};
|
|
235039
235069
|
|
|
@@ -221,96 +221,126 @@ export class IdeDiff extends HTMLElement {
|
|
|
221
221
|
const diffs = dmp.diff_main(asisSrc, tobeSrc);
|
|
222
222
|
dmp.diff_cleanupSemantic(diffs);
|
|
223
223
|
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
const
|
|
224
|
+
const asisLineDecos = [];
|
|
225
|
+
const asisMarkDecos = [];
|
|
226
|
+
const tobeLineDecos = [];
|
|
227
|
+
const tobeMarkDecos = [];
|
|
227
228
|
|
|
228
|
-
let asisCursor = 0;
|
|
229
|
-
let tobeCursor = 0;
|
|
229
|
+
let asisCursor = 0;
|
|
230
|
+
let tobeCursor = 0;
|
|
230
231
|
|
|
231
232
|
for (const [op, text] of diffs) {
|
|
232
233
|
const len = text.length;
|
|
233
234
|
|
|
234
235
|
switch (op) {
|
|
235
|
-
case diff_match_patch.DIFF_INSERT: //
|
|
236
|
-
|
|
237
|
-
tobeDecorationsToAdd.push({
|
|
236
|
+
case diff_match_patch.DIFF_INSERT: // Added text
|
|
237
|
+
tobeMarkDecos.push({
|
|
238
238
|
from: tobeCursor,
|
|
239
239
|
to: tobeCursor + len,
|
|
240
240
|
deco: Decoration.mark({ class: "cm-inserted-inline" })
|
|
241
241
|
});
|
|
242
242
|
|
|
243
|
-
// tobe 쪽에 줄 배경 데코레이션 추가 (삽입된 줄)
|
|
244
|
-
// text가 여러 줄일 수 있으므로 각 줄에 적용
|
|
245
243
|
let currentTobeLineOffset = tobeCursor;
|
|
246
244
|
const tobeLines = text.split('\n');
|
|
247
245
|
for (let i = 0; i < tobeLines.length; i++) {
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
246
|
+
// ⭐️ 중요: lineAt() 호출 전에 유효한 문서 범위 내에 있는지 확인
|
|
247
|
+
if (currentTobeLineOffset < this.#tobeEditorView.state.doc.length) {
|
|
248
|
+
const line = this.#tobeEditorView.state.doc.lineAt(currentTobeLineOffset);
|
|
249
|
+
tobeLineDecos.push({
|
|
250
|
+
from: line.from,
|
|
251
|
+
to: line.to,
|
|
252
|
+
deco: Decoration.line({ class: "cm-inserted-line-bg" })
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
// 다음 줄의 시작 위치 계산. 마지막 줄이 아니면 +1 (개행문자)
|
|
256
|
+
currentTobeLineOffset += tobeLines[i].length + (i < tobeLines.length -1 ? 1 : 0);
|
|
257
|
+
// 만약 마지막 줄이 비어있다면, 더 이상 진행하지 않도록 방지
|
|
258
|
+
if (i === tobeLines.length - 1 && tobeLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
259
|
+
// 마지막 줄이 빈 줄이고 텍스트가 개행으로 끝나지 않으면 (오프셋이 더 이상 증가할 필요 없음)
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
257
262
|
}
|
|
258
263
|
|
|
259
264
|
tobeCursor += len;
|
|
260
265
|
break;
|
|
261
266
|
|
|
262
|
-
case diff_match_patch.DIFF_DELETE: //
|
|
263
|
-
|
|
264
|
-
asisDecorationsToAdd.push({
|
|
267
|
+
case diff_match_patch.DIFF_DELETE: // Deleted text
|
|
268
|
+
asisMarkDecos.push({
|
|
265
269
|
from: asisCursor,
|
|
266
270
|
to: asisCursor + len,
|
|
267
271
|
deco: Decoration.mark({ class: "cm-deleted-inline" })
|
|
268
272
|
});
|
|
269
273
|
|
|
270
|
-
// asis 쪽에 줄 배경 데코레이션 추가 (삭제된 줄)
|
|
271
274
|
let currentAsisLineOffset = asisCursor;
|
|
272
275
|
const asisLines = text.split('\n');
|
|
273
276
|
for (let i = 0; i < asisLines.length; i++) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
277
|
+
// ⭐️ 중요: lineAt() 호출 전에 유효한 문서 범위 내에 있는지 확인
|
|
278
|
+
if (currentAsisLineOffset < this.#asisEditorView.state.doc.length) {
|
|
279
|
+
const line = this.#asisEditorView.state.doc.lineAt(currentAsisLineOffset);
|
|
280
|
+
asisLineDecos.push({
|
|
281
|
+
from: line.from,
|
|
282
|
+
to: line.to,
|
|
283
|
+
deco: Decoration.line({ class: "cm-deleted-line-bg" })
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
currentAsisLineOffset += asisLines[i].length + (i < asisLines.length -1 ? 1 : 0);
|
|
287
|
+
if (i === asisLines.length - 1 && asisLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
281
290
|
}
|
|
282
291
|
|
|
283
292
|
asisCursor += len;
|
|
284
293
|
break;
|
|
285
294
|
|
|
286
|
-
case diff_match_patch.DIFF_EQUAL: //
|
|
295
|
+
case diff_match_patch.DIFF_EQUAL: // Unchanged text
|
|
287
296
|
asisCursor += len;
|
|
288
297
|
tobeCursor += len;
|
|
289
298
|
break;
|
|
290
299
|
}
|
|
291
300
|
}
|
|
292
301
|
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
302
|
+
// Sort all collections by 'from' position (항상 좋은 습관)
|
|
303
|
+
asisLineDecos.sort((a, b) => a.from - b.from);
|
|
304
|
+
asisMarkDecos.sort((a, b) => a.from - b.from);
|
|
305
|
+
tobeLineDecos.sort((a, b) => a.from - b.from);
|
|
306
|
+
tobeMarkDecos.sort((a, b) => a.from - b.from);
|
|
296
307
|
|
|
297
|
-
//
|
|
298
|
-
const
|
|
299
|
-
for (const { from, to, deco } of
|
|
300
|
-
|
|
308
|
+
// ASIS 에디터용 줄 및 마크 데코레이션을 위한 별도 RangeSetBuilder 생성
|
|
309
|
+
const asisLineBuilder = new RangeSetBuilder();
|
|
310
|
+
for (const { from, to, deco } of asisLineDecos) {
|
|
311
|
+
asisLineBuilder.add(from, to, deco);
|
|
301
312
|
}
|
|
313
|
+
const asisMarkBuilder = new RangeSetBuilder();
|
|
314
|
+
for (const { from, to, deco } of asisMarkDecos) {
|
|
315
|
+
asisMarkBuilder.add(from, to, deco);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ASIS 에디터용 줄 및 마크 RangeSet 결합
|
|
319
|
+
const finalAsisDecorations = asisLineBuilder.finish().update({
|
|
320
|
+
add: asisMarkBuilder.finish().children
|
|
321
|
+
});
|
|
302
322
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
323
|
+
// TOBE 에디터용 줄 및 마크 데코레이션을 위한 별도 RangeSetBuilder 생성
|
|
324
|
+
const tobeLineBuilder = new RangeSetBuilder();
|
|
325
|
+
for (const { from, to, deco } of tobeLineDecos) {
|
|
326
|
+
tobeLineBuilder.add(from, to, deco);
|
|
306
327
|
}
|
|
328
|
+
const tobeMarkBuilder = new RangeSetBuilder();
|
|
329
|
+
for (const { from, to, deco } of tobeMarkDecos) {
|
|
330
|
+
tobeMarkBuilder.add(from, to, deco);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// TOBE 에디터용 줄 및 마크 RangeSet 결합
|
|
334
|
+
const finalTobeDecorations = tobeLineBuilder.finish().update({
|
|
335
|
+
add: tobeMarkBuilder.finish().children
|
|
336
|
+
});
|
|
307
337
|
|
|
308
|
-
// 데코레이션 업데이트를 위한 Effect
|
|
338
|
+
// 데코레이션 업데이트를 위한 Effect 디스패치
|
|
309
339
|
this.#asisEditorView.dispatch({
|
|
310
|
-
effects: setAsisDecorationsEffect.of(
|
|
340
|
+
effects: setAsisDecorationsEffect.of(finalAsisDecorations)
|
|
311
341
|
});
|
|
312
342
|
this.#tobeEditorView.dispatch({
|
|
313
|
-
effects: setTobeDecorationsEffect.of(
|
|
343
|
+
effects: setTobeDecorationsEffect.of(finalTobeDecorations)
|
|
314
344
|
});
|
|
315
345
|
};
|
|
316
346
|
|
package/package.json
CHANGED
|
@@ -221,96 +221,126 @@ export class IdeDiff extends HTMLElement {
|
|
|
221
221
|
const diffs = dmp.diff_main(asisSrc, tobeSrc);
|
|
222
222
|
dmp.diff_cleanupSemantic(diffs);
|
|
223
223
|
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
const
|
|
224
|
+
const asisLineDecos = [];
|
|
225
|
+
const asisMarkDecos = [];
|
|
226
|
+
const tobeLineDecos = [];
|
|
227
|
+
const tobeMarkDecos = [];
|
|
227
228
|
|
|
228
|
-
let asisCursor = 0;
|
|
229
|
-
let tobeCursor = 0;
|
|
229
|
+
let asisCursor = 0;
|
|
230
|
+
let tobeCursor = 0;
|
|
230
231
|
|
|
231
232
|
for (const [op, text] of diffs) {
|
|
232
233
|
const len = text.length;
|
|
233
234
|
|
|
234
235
|
switch (op) {
|
|
235
|
-
case diff_match_patch.DIFF_INSERT: //
|
|
236
|
-
|
|
237
|
-
tobeDecorationsToAdd.push({
|
|
236
|
+
case diff_match_patch.DIFF_INSERT: // Added text
|
|
237
|
+
tobeMarkDecos.push({
|
|
238
238
|
from: tobeCursor,
|
|
239
239
|
to: tobeCursor + len,
|
|
240
240
|
deco: Decoration.mark({ class: "cm-inserted-inline" })
|
|
241
241
|
});
|
|
242
242
|
|
|
243
|
-
// tobe 쪽에 줄 배경 데코레이션 추가 (삽입된 줄)
|
|
244
|
-
// text가 여러 줄일 수 있으므로 각 줄에 적용
|
|
245
243
|
let currentTobeLineOffset = tobeCursor;
|
|
246
244
|
const tobeLines = text.split('\n');
|
|
247
245
|
for (let i = 0; i < tobeLines.length; i++) {
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
246
|
+
// ⭐️ 중요: lineAt() 호출 전에 유효한 문서 범위 내에 있는지 확인
|
|
247
|
+
if (currentTobeLineOffset < this.#tobeEditorView.state.doc.length) {
|
|
248
|
+
const line = this.#tobeEditorView.state.doc.lineAt(currentTobeLineOffset);
|
|
249
|
+
tobeLineDecos.push({
|
|
250
|
+
from: line.from,
|
|
251
|
+
to: line.to,
|
|
252
|
+
deco: Decoration.line({ class: "cm-inserted-line-bg" })
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
// 다음 줄의 시작 위치 계산. 마지막 줄이 아니면 +1 (개행문자)
|
|
256
|
+
currentTobeLineOffset += tobeLines[i].length + (i < tobeLines.length -1 ? 1 : 0);
|
|
257
|
+
// 만약 마지막 줄이 비어있다면, 더 이상 진행하지 않도록 방지
|
|
258
|
+
if (i === tobeLines.length - 1 && tobeLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
259
|
+
// 마지막 줄이 빈 줄이고 텍스트가 개행으로 끝나지 않으면 (오프셋이 더 이상 증가할 필요 없음)
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
257
262
|
}
|
|
258
263
|
|
|
259
264
|
tobeCursor += len;
|
|
260
265
|
break;
|
|
261
266
|
|
|
262
|
-
case diff_match_patch.DIFF_DELETE: //
|
|
263
|
-
|
|
264
|
-
asisDecorationsToAdd.push({
|
|
267
|
+
case diff_match_patch.DIFF_DELETE: // Deleted text
|
|
268
|
+
asisMarkDecos.push({
|
|
265
269
|
from: asisCursor,
|
|
266
270
|
to: asisCursor + len,
|
|
267
271
|
deco: Decoration.mark({ class: "cm-deleted-inline" })
|
|
268
272
|
});
|
|
269
273
|
|
|
270
|
-
// asis 쪽에 줄 배경 데코레이션 추가 (삭제된 줄)
|
|
271
274
|
let currentAsisLineOffset = asisCursor;
|
|
272
275
|
const asisLines = text.split('\n');
|
|
273
276
|
for (let i = 0; i < asisLines.length; i++) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
277
|
+
// ⭐️ 중요: lineAt() 호출 전에 유효한 문서 범위 내에 있는지 확인
|
|
278
|
+
if (currentAsisLineOffset < this.#asisEditorView.state.doc.length) {
|
|
279
|
+
const line = this.#asisEditorView.state.doc.lineAt(currentAsisLineOffset);
|
|
280
|
+
asisLineDecos.push({
|
|
281
|
+
from: line.from,
|
|
282
|
+
to: line.to,
|
|
283
|
+
deco: Decoration.line({ class: "cm-deleted-line-bg" })
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
currentAsisLineOffset += asisLines[i].length + (i < asisLines.length -1 ? 1 : 0);
|
|
287
|
+
if (i === asisLines.length - 1 && asisLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
281
290
|
}
|
|
282
291
|
|
|
283
292
|
asisCursor += len;
|
|
284
293
|
break;
|
|
285
294
|
|
|
286
|
-
case diff_match_patch.DIFF_EQUAL: //
|
|
295
|
+
case diff_match_patch.DIFF_EQUAL: // Unchanged text
|
|
287
296
|
asisCursor += len;
|
|
288
297
|
tobeCursor += len;
|
|
289
298
|
break;
|
|
290
299
|
}
|
|
291
300
|
}
|
|
292
301
|
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
302
|
+
// Sort all collections by 'from' position (항상 좋은 습관)
|
|
303
|
+
asisLineDecos.sort((a, b) => a.from - b.from);
|
|
304
|
+
asisMarkDecos.sort((a, b) => a.from - b.from);
|
|
305
|
+
tobeLineDecos.sort((a, b) => a.from - b.from);
|
|
306
|
+
tobeMarkDecos.sort((a, b) => a.from - b.from);
|
|
296
307
|
|
|
297
|
-
//
|
|
298
|
-
const
|
|
299
|
-
for (const { from, to, deco } of
|
|
300
|
-
|
|
308
|
+
// ASIS 에디터용 줄 및 마크 데코레이션을 위한 별도 RangeSetBuilder 생성
|
|
309
|
+
const asisLineBuilder = new RangeSetBuilder();
|
|
310
|
+
for (const { from, to, deco } of asisLineDecos) {
|
|
311
|
+
asisLineBuilder.add(from, to, deco);
|
|
301
312
|
}
|
|
313
|
+
const asisMarkBuilder = new RangeSetBuilder();
|
|
314
|
+
for (const { from, to, deco } of asisMarkDecos) {
|
|
315
|
+
asisMarkBuilder.add(from, to, deco);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ASIS 에디터용 줄 및 마크 RangeSet 결합
|
|
319
|
+
const finalAsisDecorations = asisLineBuilder.finish().update({
|
|
320
|
+
add: asisMarkBuilder.finish().children
|
|
321
|
+
});
|
|
302
322
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
323
|
+
// TOBE 에디터용 줄 및 마크 데코레이션을 위한 별도 RangeSetBuilder 생성
|
|
324
|
+
const tobeLineBuilder = new RangeSetBuilder();
|
|
325
|
+
for (const { from, to, deco } of tobeLineDecos) {
|
|
326
|
+
tobeLineBuilder.add(from, to, deco);
|
|
306
327
|
}
|
|
328
|
+
const tobeMarkBuilder = new RangeSetBuilder();
|
|
329
|
+
for (const { from, to, deco } of tobeMarkDecos) {
|
|
330
|
+
tobeMarkBuilder.add(from, to, deco);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// TOBE 에디터용 줄 및 마크 RangeSet 결합
|
|
334
|
+
const finalTobeDecorations = tobeLineBuilder.finish().update({
|
|
335
|
+
add: tobeMarkBuilder.finish().children
|
|
336
|
+
});
|
|
307
337
|
|
|
308
|
-
// 데코레이션 업데이트를 위한 Effect
|
|
338
|
+
// 데코레이션 업데이트를 위한 Effect 디스패치
|
|
309
339
|
this.#asisEditorView.dispatch({
|
|
310
|
-
effects: setAsisDecorationsEffect.of(
|
|
340
|
+
effects: setAsisDecorationsEffect.of(finalAsisDecorations)
|
|
311
341
|
});
|
|
312
342
|
this.#tobeEditorView.dispatch({
|
|
313
|
-
effects: setTobeDecorationsEffect.of(
|
|
343
|
+
effects: setTobeDecorationsEffect.of(finalTobeDecorations)
|
|
314
344
|
});
|
|
315
345
|
};
|
|
316
346
|
|