ide-assi 0.384.0 → 0.387.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 +18 -42
- package/dist/bundle.esm.js +18 -42
- package/dist/components/ideDiff.js +16 -40
- package/package.json +1 -1
- package/src/components/ideDiff.js +16 -40
package/dist/bundle.cjs.js
CHANGED
|
@@ -234777,7 +234777,7 @@ function requireDiffMatchPatch () {
|
|
|
234777
234777
|
var diffMatchPatchExports = requireDiffMatchPatch();
|
|
234778
234778
|
|
|
234779
234779
|
// Diff 데코레이션을 위한 StateField 정의 (변동 없음)
|
|
234780
|
-
StateField.define({
|
|
234780
|
+
const asisDiffDecorations = StateField.define({
|
|
234781
234781
|
create() { return Decoration.none; },
|
|
234782
234782
|
update(decorations, tr) {
|
|
234783
234783
|
return tr.effects.reduce((currentDecos, effect) => {
|
|
@@ -234790,7 +234790,7 @@ StateField.define({
|
|
|
234790
234790
|
provide: f => EditorView.decorations.from(f)
|
|
234791
234791
|
});
|
|
234792
234792
|
|
|
234793
|
-
StateField.define({
|
|
234793
|
+
const tobeDiffDecorations = StateField.define({
|
|
234794
234794
|
create() { return Decoration.none; },
|
|
234795
234795
|
update(decorations, tr) {
|
|
234796
234796
|
return tr.effects.reduce((currentDecos, effect) => {
|
|
@@ -235231,7 +235231,7 @@ export default DocManager;
|
|
|
235231
235231
|
javascript(),
|
|
235232
235232
|
EditorState.readOnly.of(true),
|
|
235233
235233
|
this.#languageCompartment.of(javascript()),
|
|
235234
|
-
|
|
235234
|
+
asisDiffDecorations,
|
|
235235
235235
|
// ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
|
|
235236
235236
|
EditorView.updateListener.of((update) => {
|
|
235237
235237
|
if (update.view.contentDOM.firstChild && !update.view._initialAsisContentLoaded) {
|
|
@@ -235253,7 +235253,7 @@ export default DocManager;
|
|
|
235253
235253
|
javascript(),
|
|
235254
235254
|
EditorState.readOnly.of(true),
|
|
235255
235255
|
this.#languageCompartment.of(javascript()),
|
|
235256
|
-
|
|
235256
|
+
tobeDiffDecorations,
|
|
235257
235257
|
// ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
|
|
235258
235258
|
EditorView.updateListener.of((update) => {
|
|
235259
235259
|
if (update.view.contentDOM.firstChild && !update.view._initialTobeContentLoaded) {
|
|
@@ -235304,20 +235304,19 @@ export default DocManager;
|
|
|
235304
235304
|
this.#tobeEditorView.scrollDOM.addEventListener('scroll', this._tobeScrollHandler);
|
|
235305
235305
|
};
|
|
235306
235306
|
|
|
235307
|
+
// IdeDiff 클래스 내부
|
|
235307
235308
|
#applyDiffDecorations = (asisSrc, tobeSrc) => {
|
|
235308
235309
|
const dmp = new diffMatchPatchExports.diff_match_patch();
|
|
235309
235310
|
const diffs = dmp.diff_main(asisSrc, tobeSrc);
|
|
235310
235311
|
dmp.diff_cleanupSemantic(diffs);
|
|
235311
235312
|
|
|
235312
235313
|
const asisLineDecos = [];
|
|
235313
|
-
const asisMarkDecos = [];
|
|
235314
235314
|
const tobeLineDecos = [];
|
|
235315
|
-
const tobeMarkDecos = [];
|
|
235316
235315
|
|
|
235317
235316
|
let asisCursor = 0;
|
|
235318
235317
|
let tobeCursor = 0;
|
|
235319
235318
|
|
|
235320
|
-
//
|
|
235319
|
+
// 중요: 새로운 문서 내용을 기반으로 임시 Doc 객체를 생성합니다.
|
|
235321
235320
|
// 이 Doc 객체를 사용하여 lineAt()을 호출합니다.
|
|
235322
235321
|
const asisDoc = Text.of(asisSrc.split('\n'));
|
|
235323
235322
|
const tobeDoc = Text.of(tobeSrc.split('\n'));
|
|
@@ -235327,16 +235326,10 @@ export default DocManager;
|
|
|
235327
235326
|
|
|
235328
235327
|
switch (op) {
|
|
235329
235328
|
case diffMatchPatchExports.diff_match_patch.DIFF_INSERT: // Added text
|
|
235330
|
-
/**
|
|
235331
|
-
tobeMarkDecos.push({
|
|
235332
|
-
from: tobeCursor,
|
|
235333
|
-
to: tobeCursor + len,
|
|
235334
|
-
deco: Decoration.mark({ class: "cm-inserted-inline" })
|
|
235335
|
-
}); */
|
|
235336
|
-
|
|
235337
235329
|
let currentTobeLineOffset = tobeCursor;
|
|
235338
235330
|
const tobeLines = text.split('\n');
|
|
235339
235331
|
for (let i = 0; i < tobeLines.length; i++) {
|
|
235332
|
+
// 줄의 시작 오프셋이 tobeDoc의 길이를 넘지 않는지 확인
|
|
235340
235333
|
if (currentTobeLineOffset < tobeDoc.length) {
|
|
235341
235334
|
const line = tobeDoc.lineAt(currentTobeLineOffset);
|
|
235342
235335
|
tobeLineDecos.push({
|
|
@@ -235345,26 +235338,21 @@ export default DocManager;
|
|
|
235345
235338
|
deco: Decoration.line({ class: "cm-inserted-line-bg" })
|
|
235346
235339
|
});
|
|
235347
235340
|
}
|
|
235341
|
+
// 다음 줄의 시작 오프셋 계산 (개행 문자 고려)
|
|
235348
235342
|
currentTobeLineOffset += tobeLines[i].length + (i < tobeLines.length - 1 ? 1 : 0);
|
|
235343
|
+
// 마지막 줄이 비어 있고 개행으로 끝나지 않으면 루프 종료 (lineAt 오류 방지)
|
|
235349
235344
|
if (i === tobeLines.length - 1 && tobeLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
235350
235345
|
break;
|
|
235351
235346
|
}
|
|
235352
235347
|
}
|
|
235353
|
-
|
|
235354
235348
|
tobeCursor += len;
|
|
235355
235349
|
break;
|
|
235356
235350
|
|
|
235357
235351
|
case diffMatchPatchExports.diff_match_patch.DIFF_DELETE: // Deleted text
|
|
235358
|
-
/**
|
|
235359
|
-
asisMarkDecos.push({
|
|
235360
|
-
from: asisCursor,
|
|
235361
|
-
to: asisCursor + len,
|
|
235362
|
-
deco: Decoration.mark({ class: "cm-deleted-inline" })
|
|
235363
|
-
}); */
|
|
235364
|
-
|
|
235365
235352
|
let currentAsisLineOffset = asisCursor;
|
|
235366
235353
|
const asisLines = text.split('\n');
|
|
235367
235354
|
for (let i = 0; i < asisLines.length; i++) {
|
|
235355
|
+
// 줄의 시작 오프셋이 asisDoc의 길이를 넘지 않는지 확인
|
|
235368
235356
|
if (currentAsisLineOffset < asisDoc.length) {
|
|
235369
235357
|
const line = asisDoc.lineAt(currentAsisLineOffset);
|
|
235370
235358
|
asisLineDecos.push({
|
|
@@ -235373,12 +235361,13 @@ export default DocManager;
|
|
|
235373
235361
|
deco: Decoration.line({ class: "cm-deleted-line-bg" })
|
|
235374
235362
|
});
|
|
235375
235363
|
}
|
|
235364
|
+
// 다음 줄의 시작 오프셋 계산 (개행 문자 고려)
|
|
235376
235365
|
currentAsisLineOffset += asisLines[i].length + (i < asisLines.length - 1 ? 1 : 0);
|
|
235366
|
+
// 마지막 줄이 비어 있고 개행으로 끝나지 않으면 루프 종료 (lineAt 오류 방지)
|
|
235377
235367
|
if (i === asisLines.length - 1 && asisLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
235378
235368
|
break;
|
|
235379
235369
|
}
|
|
235380
235370
|
}
|
|
235381
|
-
|
|
235382
235371
|
asisCursor += len;
|
|
235383
235372
|
break;
|
|
235384
235373
|
|
|
@@ -235389,34 +235378,22 @@ export default DocManager;
|
|
|
235389
235378
|
}
|
|
235390
235379
|
}
|
|
235391
235380
|
|
|
235381
|
+
// 데코레이션 중복 및 겹침 방지를 위해 정렬
|
|
235392
235382
|
asisLineDecos.sort((a, b) => a.from - b.from);
|
|
235393
|
-
asisMarkDecos.sort((a, b) => a.from - b.from);
|
|
235394
235383
|
tobeLineDecos.sort((a, b) => a.from - b.from);
|
|
235395
|
-
tobeMarkDecos.sort((a, b) => a.from - b.from);
|
|
235396
235384
|
|
|
235385
|
+
// 라인 데코레이션 빌더 생성
|
|
235397
235386
|
const asisLineBuilder = new RangeSetBuilder();
|
|
235398
235387
|
for (const { from, to, deco } of asisLineDecos) {
|
|
235399
235388
|
asisLineBuilder.add(from, to, deco);
|
|
235400
235389
|
}
|
|
235401
|
-
const
|
|
235402
|
-
for (const { from, to, deco } of asisMarkDecos) {
|
|
235403
|
-
asisMarkBuilder.add(from, to, deco);
|
|
235404
|
-
}
|
|
235405
|
-
const finalAsisDecorations = asisLineBuilder.finish().update({
|
|
235406
|
-
add: asisMarkBuilder.finish().children
|
|
235407
|
-
});
|
|
235390
|
+
const finalAsisDecorations = asisLineBuilder.finish(); // ⭐️ .update({ add: ... }) 부분 제거
|
|
235408
235391
|
|
|
235409
235392
|
const tobeLineBuilder = new RangeSetBuilder();
|
|
235410
235393
|
for (const { from, to, deco } of tobeLineDecos) {
|
|
235411
235394
|
tobeLineBuilder.add(from, to, deco);
|
|
235412
235395
|
}
|
|
235413
|
-
const
|
|
235414
|
-
for (const { from, to, deco } of tobeMarkDecos) {
|
|
235415
|
-
tobeMarkBuilder.add(from, to, deco);
|
|
235416
|
-
}
|
|
235417
|
-
const finalTobeDecorations = tobeLineBuilder.finish().update({
|
|
235418
|
-
add: tobeMarkBuilder.finish().children
|
|
235419
|
-
});
|
|
235396
|
+
const finalTobeDecorations = tobeLineBuilder.finish(); // ⭐️ .update({ add: ... }) 부분 제거
|
|
235420
235397
|
|
|
235421
235398
|
return {
|
|
235422
235399
|
asisEffect: setAsisDecorationsEffect.of(finalAsisDecorations),
|
|
@@ -235442,7 +235419,7 @@ export default DocManager;
|
|
|
235442
235419
|
}
|
|
235443
235420
|
|
|
235444
235421
|
// 데코레이션 효과는 미리 계산해 둡니다.
|
|
235445
|
-
|
|
235422
|
+
const { asisEffect, tobeEffect } = this.#applyDiffDecorations(src1, src2);
|
|
235446
235423
|
|
|
235447
235424
|
// 1단계: 텍스트 내용 변경과 언어 확장을 먼저 디스패치합니다.
|
|
235448
235425
|
// 'to' 값을 현재 문서 길이 전체로 지정하여 정확한 교체를 보장합니다.
|
|
@@ -235460,7 +235437,6 @@ export default DocManager;
|
|
|
235460
235437
|
]
|
|
235461
235438
|
});
|
|
235462
235439
|
|
|
235463
|
-
/**
|
|
235464
235440
|
// ⭐️ 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화될 시간을 줍니다.
|
|
235465
235441
|
// 다음 프레임에서 데코레이션 효과만 별도로 디스패치합니다.
|
|
235466
235442
|
requestAnimationFrame(() => {
|
|
@@ -235479,7 +235455,7 @@ export default DocManager;
|
|
|
235479
235455
|
// this.#asisEditorView.scrollDOM.scrollTop = 0;
|
|
235480
235456
|
// this.#tobeEditorView.scrollDOM.scrollTop = 0;
|
|
235481
235457
|
});
|
|
235482
|
-
});
|
|
235458
|
+
});
|
|
235483
235459
|
};
|
|
235484
235460
|
|
|
235485
235461
|
disconnectedCallback() {
|
package/dist/bundle.esm.js
CHANGED
|
@@ -234773,7 +234773,7 @@ function requireDiffMatchPatch () {
|
|
|
234773
234773
|
var diffMatchPatchExports = requireDiffMatchPatch();
|
|
234774
234774
|
|
|
234775
234775
|
// Diff 데코레이션을 위한 StateField 정의 (변동 없음)
|
|
234776
|
-
StateField.define({
|
|
234776
|
+
const asisDiffDecorations = StateField.define({
|
|
234777
234777
|
create() { return Decoration.none; },
|
|
234778
234778
|
update(decorations, tr) {
|
|
234779
234779
|
return tr.effects.reduce((currentDecos, effect) => {
|
|
@@ -234786,7 +234786,7 @@ StateField.define({
|
|
|
234786
234786
|
provide: f => EditorView.decorations.from(f)
|
|
234787
234787
|
});
|
|
234788
234788
|
|
|
234789
|
-
StateField.define({
|
|
234789
|
+
const tobeDiffDecorations = StateField.define({
|
|
234790
234790
|
create() { return Decoration.none; },
|
|
234791
234791
|
update(decorations, tr) {
|
|
234792
234792
|
return tr.effects.reduce((currentDecos, effect) => {
|
|
@@ -235227,7 +235227,7 @@ export default DocManager;
|
|
|
235227
235227
|
javascript(),
|
|
235228
235228
|
EditorState.readOnly.of(true),
|
|
235229
235229
|
this.#languageCompartment.of(javascript()),
|
|
235230
|
-
|
|
235230
|
+
asisDiffDecorations,
|
|
235231
235231
|
// ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
|
|
235232
235232
|
EditorView.updateListener.of((update) => {
|
|
235233
235233
|
if (update.view.contentDOM.firstChild && !update.view._initialAsisContentLoaded) {
|
|
@@ -235249,7 +235249,7 @@ export default DocManager;
|
|
|
235249
235249
|
javascript(),
|
|
235250
235250
|
EditorState.readOnly.of(true),
|
|
235251
235251
|
this.#languageCompartment.of(javascript()),
|
|
235252
|
-
|
|
235252
|
+
tobeDiffDecorations,
|
|
235253
235253
|
// ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
|
|
235254
235254
|
EditorView.updateListener.of((update) => {
|
|
235255
235255
|
if (update.view.contentDOM.firstChild && !update.view._initialTobeContentLoaded) {
|
|
@@ -235300,20 +235300,19 @@ export default DocManager;
|
|
|
235300
235300
|
this.#tobeEditorView.scrollDOM.addEventListener('scroll', this._tobeScrollHandler);
|
|
235301
235301
|
};
|
|
235302
235302
|
|
|
235303
|
+
// IdeDiff 클래스 내부
|
|
235303
235304
|
#applyDiffDecorations = (asisSrc, tobeSrc) => {
|
|
235304
235305
|
const dmp = new diffMatchPatchExports.diff_match_patch();
|
|
235305
235306
|
const diffs = dmp.diff_main(asisSrc, tobeSrc);
|
|
235306
235307
|
dmp.diff_cleanupSemantic(diffs);
|
|
235307
235308
|
|
|
235308
235309
|
const asisLineDecos = [];
|
|
235309
|
-
const asisMarkDecos = [];
|
|
235310
235310
|
const tobeLineDecos = [];
|
|
235311
|
-
const tobeMarkDecos = [];
|
|
235312
235311
|
|
|
235313
235312
|
let asisCursor = 0;
|
|
235314
235313
|
let tobeCursor = 0;
|
|
235315
235314
|
|
|
235316
|
-
//
|
|
235315
|
+
// 중요: 새로운 문서 내용을 기반으로 임시 Doc 객체를 생성합니다.
|
|
235317
235316
|
// 이 Doc 객체를 사용하여 lineAt()을 호출합니다.
|
|
235318
235317
|
const asisDoc = Text.of(asisSrc.split('\n'));
|
|
235319
235318
|
const tobeDoc = Text.of(tobeSrc.split('\n'));
|
|
@@ -235323,16 +235322,10 @@ export default DocManager;
|
|
|
235323
235322
|
|
|
235324
235323
|
switch (op) {
|
|
235325
235324
|
case diffMatchPatchExports.diff_match_patch.DIFF_INSERT: // Added text
|
|
235326
|
-
/**
|
|
235327
|
-
tobeMarkDecos.push({
|
|
235328
|
-
from: tobeCursor,
|
|
235329
|
-
to: tobeCursor + len,
|
|
235330
|
-
deco: Decoration.mark({ class: "cm-inserted-inline" })
|
|
235331
|
-
}); */
|
|
235332
|
-
|
|
235333
235325
|
let currentTobeLineOffset = tobeCursor;
|
|
235334
235326
|
const tobeLines = text.split('\n');
|
|
235335
235327
|
for (let i = 0; i < tobeLines.length; i++) {
|
|
235328
|
+
// 줄의 시작 오프셋이 tobeDoc의 길이를 넘지 않는지 확인
|
|
235336
235329
|
if (currentTobeLineOffset < tobeDoc.length) {
|
|
235337
235330
|
const line = tobeDoc.lineAt(currentTobeLineOffset);
|
|
235338
235331
|
tobeLineDecos.push({
|
|
@@ -235341,26 +235334,21 @@ export default DocManager;
|
|
|
235341
235334
|
deco: Decoration.line({ class: "cm-inserted-line-bg" })
|
|
235342
235335
|
});
|
|
235343
235336
|
}
|
|
235337
|
+
// 다음 줄의 시작 오프셋 계산 (개행 문자 고려)
|
|
235344
235338
|
currentTobeLineOffset += tobeLines[i].length + (i < tobeLines.length - 1 ? 1 : 0);
|
|
235339
|
+
// 마지막 줄이 비어 있고 개행으로 끝나지 않으면 루프 종료 (lineAt 오류 방지)
|
|
235345
235340
|
if (i === tobeLines.length - 1 && tobeLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
235346
235341
|
break;
|
|
235347
235342
|
}
|
|
235348
235343
|
}
|
|
235349
|
-
|
|
235350
235344
|
tobeCursor += len;
|
|
235351
235345
|
break;
|
|
235352
235346
|
|
|
235353
235347
|
case diffMatchPatchExports.diff_match_patch.DIFF_DELETE: // Deleted text
|
|
235354
|
-
/**
|
|
235355
|
-
asisMarkDecos.push({
|
|
235356
|
-
from: asisCursor,
|
|
235357
|
-
to: asisCursor + len,
|
|
235358
|
-
deco: Decoration.mark({ class: "cm-deleted-inline" })
|
|
235359
|
-
}); */
|
|
235360
|
-
|
|
235361
235348
|
let currentAsisLineOffset = asisCursor;
|
|
235362
235349
|
const asisLines = text.split('\n');
|
|
235363
235350
|
for (let i = 0; i < asisLines.length; i++) {
|
|
235351
|
+
// 줄의 시작 오프셋이 asisDoc의 길이를 넘지 않는지 확인
|
|
235364
235352
|
if (currentAsisLineOffset < asisDoc.length) {
|
|
235365
235353
|
const line = asisDoc.lineAt(currentAsisLineOffset);
|
|
235366
235354
|
asisLineDecos.push({
|
|
@@ -235369,12 +235357,13 @@ export default DocManager;
|
|
|
235369
235357
|
deco: Decoration.line({ class: "cm-deleted-line-bg" })
|
|
235370
235358
|
});
|
|
235371
235359
|
}
|
|
235360
|
+
// 다음 줄의 시작 오프셋 계산 (개행 문자 고려)
|
|
235372
235361
|
currentAsisLineOffset += asisLines[i].length + (i < asisLines.length - 1 ? 1 : 0);
|
|
235362
|
+
// 마지막 줄이 비어 있고 개행으로 끝나지 않으면 루프 종료 (lineAt 오류 방지)
|
|
235373
235363
|
if (i === asisLines.length - 1 && asisLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
235374
235364
|
break;
|
|
235375
235365
|
}
|
|
235376
235366
|
}
|
|
235377
|
-
|
|
235378
235367
|
asisCursor += len;
|
|
235379
235368
|
break;
|
|
235380
235369
|
|
|
@@ -235385,34 +235374,22 @@ export default DocManager;
|
|
|
235385
235374
|
}
|
|
235386
235375
|
}
|
|
235387
235376
|
|
|
235377
|
+
// 데코레이션 중복 및 겹침 방지를 위해 정렬
|
|
235388
235378
|
asisLineDecos.sort((a, b) => a.from - b.from);
|
|
235389
|
-
asisMarkDecos.sort((a, b) => a.from - b.from);
|
|
235390
235379
|
tobeLineDecos.sort((a, b) => a.from - b.from);
|
|
235391
|
-
tobeMarkDecos.sort((a, b) => a.from - b.from);
|
|
235392
235380
|
|
|
235381
|
+
// 라인 데코레이션 빌더 생성
|
|
235393
235382
|
const asisLineBuilder = new RangeSetBuilder();
|
|
235394
235383
|
for (const { from, to, deco } of asisLineDecos) {
|
|
235395
235384
|
asisLineBuilder.add(from, to, deco);
|
|
235396
235385
|
}
|
|
235397
|
-
const
|
|
235398
|
-
for (const { from, to, deco } of asisMarkDecos) {
|
|
235399
|
-
asisMarkBuilder.add(from, to, deco);
|
|
235400
|
-
}
|
|
235401
|
-
const finalAsisDecorations = asisLineBuilder.finish().update({
|
|
235402
|
-
add: asisMarkBuilder.finish().children
|
|
235403
|
-
});
|
|
235386
|
+
const finalAsisDecorations = asisLineBuilder.finish(); // ⭐️ .update({ add: ... }) 부분 제거
|
|
235404
235387
|
|
|
235405
235388
|
const tobeLineBuilder = new RangeSetBuilder();
|
|
235406
235389
|
for (const { from, to, deco } of tobeLineDecos) {
|
|
235407
235390
|
tobeLineBuilder.add(from, to, deco);
|
|
235408
235391
|
}
|
|
235409
|
-
const
|
|
235410
|
-
for (const { from, to, deco } of tobeMarkDecos) {
|
|
235411
|
-
tobeMarkBuilder.add(from, to, deco);
|
|
235412
|
-
}
|
|
235413
|
-
const finalTobeDecorations = tobeLineBuilder.finish().update({
|
|
235414
|
-
add: tobeMarkBuilder.finish().children
|
|
235415
|
-
});
|
|
235392
|
+
const finalTobeDecorations = tobeLineBuilder.finish(); // ⭐️ .update({ add: ... }) 부분 제거
|
|
235416
235393
|
|
|
235417
235394
|
return {
|
|
235418
235395
|
asisEffect: setAsisDecorationsEffect.of(finalAsisDecorations),
|
|
@@ -235438,7 +235415,7 @@ export default DocManager;
|
|
|
235438
235415
|
}
|
|
235439
235416
|
|
|
235440
235417
|
// 데코레이션 효과는 미리 계산해 둡니다.
|
|
235441
|
-
|
|
235418
|
+
const { asisEffect, tobeEffect } = this.#applyDiffDecorations(src1, src2);
|
|
235442
235419
|
|
|
235443
235420
|
// 1단계: 텍스트 내용 변경과 언어 확장을 먼저 디스패치합니다.
|
|
235444
235421
|
// 'to' 값을 현재 문서 길이 전체로 지정하여 정확한 교체를 보장합니다.
|
|
@@ -235456,7 +235433,6 @@ export default DocManager;
|
|
|
235456
235433
|
]
|
|
235457
235434
|
});
|
|
235458
235435
|
|
|
235459
|
-
/**
|
|
235460
235436
|
// ⭐️ 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화될 시간을 줍니다.
|
|
235461
235437
|
// 다음 프레임에서 데코레이션 효과만 별도로 디스패치합니다.
|
|
235462
235438
|
requestAnimationFrame(() => {
|
|
@@ -235475,7 +235451,7 @@ export default DocManager;
|
|
|
235475
235451
|
// this.#asisEditorView.scrollDOM.scrollTop = 0;
|
|
235476
235452
|
// this.#tobeEditorView.scrollDOM.scrollTop = 0;
|
|
235477
235453
|
});
|
|
235478
|
-
});
|
|
235454
|
+
});
|
|
235479
235455
|
};
|
|
235480
235456
|
|
|
235481
235457
|
disconnectedCallback() {
|
|
@@ -479,7 +479,7 @@ export default DocManager;
|
|
|
479
479
|
javascript(),
|
|
480
480
|
EditorState.readOnly.of(true),
|
|
481
481
|
this.#languageCompartment.of(javascript()),
|
|
482
|
-
|
|
482
|
+
asisDiffDecorations,
|
|
483
483
|
// ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
|
|
484
484
|
EditorView.updateListener.of((update) => {
|
|
485
485
|
if (update.view.contentDOM.firstChild && !update.view._initialAsisContentLoaded) {
|
|
@@ -501,7 +501,7 @@ export default DocManager;
|
|
|
501
501
|
javascript(),
|
|
502
502
|
EditorState.readOnly.of(true),
|
|
503
503
|
this.#languageCompartment.of(javascript()),
|
|
504
|
-
|
|
504
|
+
tobeDiffDecorations,
|
|
505
505
|
// ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
|
|
506
506
|
EditorView.updateListener.of((update) => {
|
|
507
507
|
if (update.view.contentDOM.firstChild && !update.view._initialTobeContentLoaded) {
|
|
@@ -552,20 +552,19 @@ export default DocManager;
|
|
|
552
552
|
this.#tobeEditorView.scrollDOM.addEventListener('scroll', this._tobeScrollHandler);
|
|
553
553
|
};
|
|
554
554
|
|
|
555
|
+
// IdeDiff 클래스 내부
|
|
555
556
|
#applyDiffDecorations = (asisSrc, tobeSrc) => {
|
|
556
557
|
const dmp = new diff_match_patch();
|
|
557
558
|
const diffs = dmp.diff_main(asisSrc, tobeSrc);
|
|
558
559
|
dmp.diff_cleanupSemantic(diffs);
|
|
559
560
|
|
|
560
561
|
const asisLineDecos = [];
|
|
561
|
-
const asisMarkDecos = [];
|
|
562
562
|
const tobeLineDecos = [];
|
|
563
|
-
const tobeMarkDecos = [];
|
|
564
563
|
|
|
565
564
|
let asisCursor = 0;
|
|
566
565
|
let tobeCursor = 0;
|
|
567
566
|
|
|
568
|
-
//
|
|
567
|
+
// 중요: 새로운 문서 내용을 기반으로 임시 Doc 객체를 생성합니다.
|
|
569
568
|
// 이 Doc 객체를 사용하여 lineAt()을 호출합니다.
|
|
570
569
|
const asisDoc = Text.of(asisSrc.split('\n'));
|
|
571
570
|
const tobeDoc = Text.of(tobeSrc.split('\n'));
|
|
@@ -575,16 +574,10 @@ export default DocManager;
|
|
|
575
574
|
|
|
576
575
|
switch (op) {
|
|
577
576
|
case diff_match_patch.DIFF_INSERT: // Added text
|
|
578
|
-
/**
|
|
579
|
-
tobeMarkDecos.push({
|
|
580
|
-
from: tobeCursor,
|
|
581
|
-
to: tobeCursor + len,
|
|
582
|
-
deco: Decoration.mark({ class: "cm-inserted-inline" })
|
|
583
|
-
}); */
|
|
584
|
-
|
|
585
577
|
let currentTobeLineOffset = tobeCursor;
|
|
586
578
|
const tobeLines = text.split('\n');
|
|
587
579
|
for (let i = 0; i < tobeLines.length; i++) {
|
|
580
|
+
// 줄의 시작 오프셋이 tobeDoc의 길이를 넘지 않는지 확인
|
|
588
581
|
if (currentTobeLineOffset < tobeDoc.length) {
|
|
589
582
|
const line = tobeDoc.lineAt(currentTobeLineOffset);
|
|
590
583
|
tobeLineDecos.push({
|
|
@@ -593,26 +586,21 @@ export default DocManager;
|
|
|
593
586
|
deco: Decoration.line({ class: "cm-inserted-line-bg" })
|
|
594
587
|
});
|
|
595
588
|
}
|
|
589
|
+
// 다음 줄의 시작 오프셋 계산 (개행 문자 고려)
|
|
596
590
|
currentTobeLineOffset += tobeLines[i].length + (i < tobeLines.length - 1 ? 1 : 0);
|
|
591
|
+
// 마지막 줄이 비어 있고 개행으로 끝나지 않으면 루프 종료 (lineAt 오류 방지)
|
|
597
592
|
if (i === tobeLines.length - 1 && tobeLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
598
593
|
break;
|
|
599
594
|
}
|
|
600
595
|
}
|
|
601
|
-
|
|
602
596
|
tobeCursor += len;
|
|
603
597
|
break;
|
|
604
598
|
|
|
605
599
|
case diff_match_patch.DIFF_DELETE: // Deleted text
|
|
606
|
-
/**
|
|
607
|
-
asisMarkDecos.push({
|
|
608
|
-
from: asisCursor,
|
|
609
|
-
to: asisCursor + len,
|
|
610
|
-
deco: Decoration.mark({ class: "cm-deleted-inline" })
|
|
611
|
-
}); */
|
|
612
|
-
|
|
613
600
|
let currentAsisLineOffset = asisCursor;
|
|
614
601
|
const asisLines = text.split('\n');
|
|
615
602
|
for (let i = 0; i < asisLines.length; i++) {
|
|
603
|
+
// 줄의 시작 오프셋이 asisDoc의 길이를 넘지 않는지 확인
|
|
616
604
|
if (currentAsisLineOffset < asisDoc.length) {
|
|
617
605
|
const line = asisDoc.lineAt(currentAsisLineOffset);
|
|
618
606
|
asisLineDecos.push({
|
|
@@ -621,12 +609,13 @@ export default DocManager;
|
|
|
621
609
|
deco: Decoration.line({ class: "cm-deleted-line-bg" })
|
|
622
610
|
});
|
|
623
611
|
}
|
|
612
|
+
// 다음 줄의 시작 오프셋 계산 (개행 문자 고려)
|
|
624
613
|
currentAsisLineOffset += asisLines[i].length + (i < asisLines.length - 1 ? 1 : 0);
|
|
614
|
+
// 마지막 줄이 비어 있고 개행으로 끝나지 않으면 루프 종료 (lineAt 오류 방지)
|
|
625
615
|
if (i === asisLines.length - 1 && asisLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
626
616
|
break;
|
|
627
617
|
}
|
|
628
618
|
}
|
|
629
|
-
|
|
630
619
|
asisCursor += len;
|
|
631
620
|
break;
|
|
632
621
|
|
|
@@ -637,34 +626,22 @@ export default DocManager;
|
|
|
637
626
|
}
|
|
638
627
|
}
|
|
639
628
|
|
|
629
|
+
// 데코레이션 중복 및 겹침 방지를 위해 정렬
|
|
640
630
|
asisLineDecos.sort((a, b) => a.from - b.from);
|
|
641
|
-
asisMarkDecos.sort((a, b) => a.from - b.from);
|
|
642
631
|
tobeLineDecos.sort((a, b) => a.from - b.from);
|
|
643
|
-
tobeMarkDecos.sort((a, b) => a.from - b.from);
|
|
644
632
|
|
|
633
|
+
// 라인 데코레이션 빌더 생성
|
|
645
634
|
const asisLineBuilder = new RangeSetBuilder();
|
|
646
635
|
for (const { from, to, deco } of asisLineDecos) {
|
|
647
636
|
asisLineBuilder.add(from, to, deco);
|
|
648
637
|
}
|
|
649
|
-
const
|
|
650
|
-
for (const { from, to, deco } of asisMarkDecos) {
|
|
651
|
-
asisMarkBuilder.add(from, to, deco);
|
|
652
|
-
}
|
|
653
|
-
const finalAsisDecorations = asisLineBuilder.finish().update({
|
|
654
|
-
add: asisMarkBuilder.finish().children
|
|
655
|
-
});
|
|
638
|
+
const finalAsisDecorations = asisLineBuilder.finish(); // ⭐️ .update({ add: ... }) 부분 제거
|
|
656
639
|
|
|
657
640
|
const tobeLineBuilder = new RangeSetBuilder();
|
|
658
641
|
for (const { from, to, deco } of tobeLineDecos) {
|
|
659
642
|
tobeLineBuilder.add(from, to, deco);
|
|
660
643
|
}
|
|
661
|
-
const
|
|
662
|
-
for (const { from, to, deco } of tobeMarkDecos) {
|
|
663
|
-
tobeMarkBuilder.add(from, to, deco);
|
|
664
|
-
}
|
|
665
|
-
const finalTobeDecorations = tobeLineBuilder.finish().update({
|
|
666
|
-
add: tobeMarkBuilder.finish().children
|
|
667
|
-
});
|
|
644
|
+
const finalTobeDecorations = tobeLineBuilder.finish(); // ⭐️ .update({ add: ... }) 부분 제거
|
|
668
645
|
|
|
669
646
|
return {
|
|
670
647
|
asisEffect: setAsisDecorationsEffect.of(finalAsisDecorations),
|
|
@@ -690,7 +667,7 @@ export default DocManager;
|
|
|
690
667
|
}
|
|
691
668
|
|
|
692
669
|
// 데코레이션 효과는 미리 계산해 둡니다.
|
|
693
|
-
|
|
670
|
+
const { asisEffect, tobeEffect } = this.#applyDiffDecorations(src1, src2);
|
|
694
671
|
|
|
695
672
|
// 1단계: 텍스트 내용 변경과 언어 확장을 먼저 디스패치합니다.
|
|
696
673
|
// 'to' 값을 현재 문서 길이 전체로 지정하여 정확한 교체를 보장합니다.
|
|
@@ -708,7 +685,6 @@ export default DocManager;
|
|
|
708
685
|
]
|
|
709
686
|
});
|
|
710
687
|
|
|
711
|
-
/**
|
|
712
688
|
// ⭐️ 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화될 시간을 줍니다.
|
|
713
689
|
// 다음 프레임에서 데코레이션 효과만 별도로 디스패치합니다.
|
|
714
690
|
requestAnimationFrame(() => {
|
|
@@ -727,7 +703,7 @@ export default DocManager;
|
|
|
727
703
|
// this.#asisEditorView.scrollDOM.scrollTop = 0;
|
|
728
704
|
// this.#tobeEditorView.scrollDOM.scrollTop = 0;
|
|
729
705
|
});
|
|
730
|
-
});
|
|
706
|
+
});
|
|
731
707
|
};
|
|
732
708
|
|
|
733
709
|
disconnectedCallback() {
|
package/package.json
CHANGED
|
@@ -479,7 +479,7 @@ export default DocManager;
|
|
|
479
479
|
javascript(),
|
|
480
480
|
EditorState.readOnly.of(true),
|
|
481
481
|
this.#languageCompartment.of(javascript()),
|
|
482
|
-
|
|
482
|
+
asisDiffDecorations,
|
|
483
483
|
// ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
|
|
484
484
|
EditorView.updateListener.of((update) => {
|
|
485
485
|
if (update.view.contentDOM.firstChild && !update.view._initialAsisContentLoaded) {
|
|
@@ -501,7 +501,7 @@ export default DocManager;
|
|
|
501
501
|
javascript(),
|
|
502
502
|
EditorState.readOnly.of(true),
|
|
503
503
|
this.#languageCompartment.of(javascript()),
|
|
504
|
-
|
|
504
|
+
tobeDiffDecorations,
|
|
505
505
|
// ⭐️ updateListener는 유지: 뷰가 DOM에 완전히 렌더링될 때까지 기다림
|
|
506
506
|
EditorView.updateListener.of((update) => {
|
|
507
507
|
if (update.view.contentDOM.firstChild && !update.view._initialTobeContentLoaded) {
|
|
@@ -552,20 +552,19 @@ export default DocManager;
|
|
|
552
552
|
this.#tobeEditorView.scrollDOM.addEventListener('scroll', this._tobeScrollHandler);
|
|
553
553
|
};
|
|
554
554
|
|
|
555
|
+
// IdeDiff 클래스 내부
|
|
555
556
|
#applyDiffDecorations = (asisSrc, tobeSrc) => {
|
|
556
557
|
const dmp = new diff_match_patch();
|
|
557
558
|
const diffs = dmp.diff_main(asisSrc, tobeSrc);
|
|
558
559
|
dmp.diff_cleanupSemantic(diffs);
|
|
559
560
|
|
|
560
561
|
const asisLineDecos = [];
|
|
561
|
-
const asisMarkDecos = [];
|
|
562
562
|
const tobeLineDecos = [];
|
|
563
|
-
const tobeMarkDecos = [];
|
|
564
563
|
|
|
565
564
|
let asisCursor = 0;
|
|
566
565
|
let tobeCursor = 0;
|
|
567
566
|
|
|
568
|
-
//
|
|
567
|
+
// 중요: 새로운 문서 내용을 기반으로 임시 Doc 객체를 생성합니다.
|
|
569
568
|
// 이 Doc 객체를 사용하여 lineAt()을 호출합니다.
|
|
570
569
|
const asisDoc = Text.of(asisSrc.split('\n'));
|
|
571
570
|
const tobeDoc = Text.of(tobeSrc.split('\n'));
|
|
@@ -575,16 +574,10 @@ export default DocManager;
|
|
|
575
574
|
|
|
576
575
|
switch (op) {
|
|
577
576
|
case diff_match_patch.DIFF_INSERT: // Added text
|
|
578
|
-
/**
|
|
579
|
-
tobeMarkDecos.push({
|
|
580
|
-
from: tobeCursor,
|
|
581
|
-
to: tobeCursor + len,
|
|
582
|
-
deco: Decoration.mark({ class: "cm-inserted-inline" })
|
|
583
|
-
}); */
|
|
584
|
-
|
|
585
577
|
let currentTobeLineOffset = tobeCursor;
|
|
586
578
|
const tobeLines = text.split('\n');
|
|
587
579
|
for (let i = 0; i < tobeLines.length; i++) {
|
|
580
|
+
// 줄의 시작 오프셋이 tobeDoc의 길이를 넘지 않는지 확인
|
|
588
581
|
if (currentTobeLineOffset < tobeDoc.length) {
|
|
589
582
|
const line = tobeDoc.lineAt(currentTobeLineOffset);
|
|
590
583
|
tobeLineDecos.push({
|
|
@@ -593,26 +586,21 @@ export default DocManager;
|
|
|
593
586
|
deco: Decoration.line({ class: "cm-inserted-line-bg" })
|
|
594
587
|
});
|
|
595
588
|
}
|
|
589
|
+
// 다음 줄의 시작 오프셋 계산 (개행 문자 고려)
|
|
596
590
|
currentTobeLineOffset += tobeLines[i].length + (i < tobeLines.length - 1 ? 1 : 0);
|
|
591
|
+
// 마지막 줄이 비어 있고 개행으로 끝나지 않으면 루프 종료 (lineAt 오류 방지)
|
|
597
592
|
if (i === tobeLines.length - 1 && tobeLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
598
593
|
break;
|
|
599
594
|
}
|
|
600
595
|
}
|
|
601
|
-
|
|
602
596
|
tobeCursor += len;
|
|
603
597
|
break;
|
|
604
598
|
|
|
605
599
|
case diff_match_patch.DIFF_DELETE: // Deleted text
|
|
606
|
-
/**
|
|
607
|
-
asisMarkDecos.push({
|
|
608
|
-
from: asisCursor,
|
|
609
|
-
to: asisCursor + len,
|
|
610
|
-
deco: Decoration.mark({ class: "cm-deleted-inline" })
|
|
611
|
-
}); */
|
|
612
|
-
|
|
613
600
|
let currentAsisLineOffset = asisCursor;
|
|
614
601
|
const asisLines = text.split('\n');
|
|
615
602
|
for (let i = 0; i < asisLines.length; i++) {
|
|
603
|
+
// 줄의 시작 오프셋이 asisDoc의 길이를 넘지 않는지 확인
|
|
616
604
|
if (currentAsisLineOffset < asisDoc.length) {
|
|
617
605
|
const line = asisDoc.lineAt(currentAsisLineOffset);
|
|
618
606
|
asisLineDecos.push({
|
|
@@ -621,12 +609,13 @@ export default DocManager;
|
|
|
621
609
|
deco: Decoration.line({ class: "cm-deleted-line-bg" })
|
|
622
610
|
});
|
|
623
611
|
}
|
|
612
|
+
// 다음 줄의 시작 오프셋 계산 (개행 문자 고려)
|
|
624
613
|
currentAsisLineOffset += asisLines[i].length + (i < asisLines.length - 1 ? 1 : 0);
|
|
614
|
+
// 마지막 줄이 비어 있고 개행으로 끝나지 않으면 루프 종료 (lineAt 오류 방지)
|
|
625
615
|
if (i === asisLines.length - 1 && asisLines[i].length === 0 && text.endsWith('\n') === false) {
|
|
626
616
|
break;
|
|
627
617
|
}
|
|
628
618
|
}
|
|
629
|
-
|
|
630
619
|
asisCursor += len;
|
|
631
620
|
break;
|
|
632
621
|
|
|
@@ -637,34 +626,22 @@ export default DocManager;
|
|
|
637
626
|
}
|
|
638
627
|
}
|
|
639
628
|
|
|
629
|
+
// 데코레이션 중복 및 겹침 방지를 위해 정렬
|
|
640
630
|
asisLineDecos.sort((a, b) => a.from - b.from);
|
|
641
|
-
asisMarkDecos.sort((a, b) => a.from - b.from);
|
|
642
631
|
tobeLineDecos.sort((a, b) => a.from - b.from);
|
|
643
|
-
tobeMarkDecos.sort((a, b) => a.from - b.from);
|
|
644
632
|
|
|
633
|
+
// 라인 데코레이션 빌더 생성
|
|
645
634
|
const asisLineBuilder = new RangeSetBuilder();
|
|
646
635
|
for (const { from, to, deco } of asisLineDecos) {
|
|
647
636
|
asisLineBuilder.add(from, to, deco);
|
|
648
637
|
}
|
|
649
|
-
const
|
|
650
|
-
for (const { from, to, deco } of asisMarkDecos) {
|
|
651
|
-
asisMarkBuilder.add(from, to, deco);
|
|
652
|
-
}
|
|
653
|
-
const finalAsisDecorations = asisLineBuilder.finish().update({
|
|
654
|
-
add: asisMarkBuilder.finish().children
|
|
655
|
-
});
|
|
638
|
+
const finalAsisDecorations = asisLineBuilder.finish(); // ⭐️ .update({ add: ... }) 부분 제거
|
|
656
639
|
|
|
657
640
|
const tobeLineBuilder = new RangeSetBuilder();
|
|
658
641
|
for (const { from, to, deco } of tobeLineDecos) {
|
|
659
642
|
tobeLineBuilder.add(from, to, deco);
|
|
660
643
|
}
|
|
661
|
-
const
|
|
662
|
-
for (const { from, to, deco } of tobeMarkDecos) {
|
|
663
|
-
tobeMarkBuilder.add(from, to, deco);
|
|
664
|
-
}
|
|
665
|
-
const finalTobeDecorations = tobeLineBuilder.finish().update({
|
|
666
|
-
add: tobeMarkBuilder.finish().children
|
|
667
|
-
});
|
|
644
|
+
const finalTobeDecorations = tobeLineBuilder.finish(); // ⭐️ .update({ add: ... }) 부분 제거
|
|
668
645
|
|
|
669
646
|
return {
|
|
670
647
|
asisEffect: setAsisDecorationsEffect.of(finalAsisDecorations),
|
|
@@ -690,7 +667,7 @@ export default DocManager;
|
|
|
690
667
|
}
|
|
691
668
|
|
|
692
669
|
// 데코레이션 효과는 미리 계산해 둡니다.
|
|
693
|
-
|
|
670
|
+
const { asisEffect, tobeEffect } = this.#applyDiffDecorations(src1, src2);
|
|
694
671
|
|
|
695
672
|
// 1단계: 텍스트 내용 변경과 언어 확장을 먼저 디스패치합니다.
|
|
696
673
|
// 'to' 값을 현재 문서 길이 전체로 지정하여 정확한 교체를 보장합니다.
|
|
@@ -708,7 +685,6 @@ export default DocManager;
|
|
|
708
685
|
]
|
|
709
686
|
});
|
|
710
687
|
|
|
711
|
-
/**
|
|
712
688
|
// ⭐️ 2단계: 텍스트 및 언어 변경이 완전히 적용되고 뷰가 안정화될 시간을 줍니다.
|
|
713
689
|
// 다음 프레임에서 데코레이션 효과만 별도로 디스패치합니다.
|
|
714
690
|
requestAnimationFrame(() => {
|
|
@@ -727,7 +703,7 @@ export default DocManager;
|
|
|
727
703
|
// this.#asisEditorView.scrollDOM.scrollTop = 0;
|
|
728
704
|
// this.#tobeEditorView.scrollDOM.scrollTop = 0;
|
|
729
705
|
});
|
|
730
|
-
});
|
|
706
|
+
});
|
|
731
707
|
};
|
|
732
708
|
|
|
733
709
|
disconnectedCallback() {
|