📦 Initialize Geulbeot structure and merge Prompts & test projects

This commit is contained in:
2026-03-05 11:32:29 +09:00
commit 555a954458
687 changed files with 205247 additions and 0 deletions

View File

@@ -0,0 +1,143 @@
// ===== AI 부분 수정 =====
function setupIframeSelection() {
const frame = document.getElementById('previewFrame');
if (!frame.contentDocument) return;
// 블록 선택 시 텍스트만 저장 (팝업 안 띄움)
frame.contentDocument.addEventListener('mouseup', function(e) {
const selection = frame.contentWindow.getSelection();
const text = selection.toString().trim();
if (text.length > 0) {
selectedText = text;
selectedRange = selection.getRangeAt(0).cloneRange();
// 툴바의 AI 버튼 활성화 표시
const aiBtn = document.getElementById('aiEditToolbarBtn');
if (aiBtn) {
aiBtn.classList.add('has-selection');
aiBtn.title = `AI 수정 (${text.length}자 선택됨)`;
}
} else {
selectedText = '';
selectedRange = null;
const aiBtn = document.getElementById('aiEditToolbarBtn');
if (aiBtn) {
aiBtn.classList.remove('has-selection');
aiBtn.title = 'AI 수정 (텍스트를 먼저 선택하세요)';
}
}
});
}
// 툴바 버튼 클릭 시 AI 편집 팝업 표시
function triggerAiEdit() {
if (!selectedText || selectedText.length === 0) {
alert('먼저 수정할 텍스트를 드래그하여 선택해주세요.');
return;
}
showAiEditPopup(selectedText);
}
function showAiEditPopup(text) {
const popup = document.getElementById('aiEditPopup');
const textDisplay = document.getElementById('aiEditSelectedText');
const displayText = text.length > 150 ? text.substring(0, 150) + '...' : text;
textDisplay.textContent = displayText;
popup.classList.add('show');
document.getElementById('aiEditInput').focus();
}
function closeAiEditPopup() {
document.getElementById('aiEditPopup').classList.remove('show');
document.getElementById('aiEditInput').value = '';
}
async function submitAiEdit() {
const request = document.getElementById('aiEditInput').value.trim();
if (!request) {
alert('수정 요청을 입력해주세요.');
return;
}
if (!selectedText) {
alert('선택된 텍스트가 없습니다.');
return;
}
const btn = document.querySelector('.ai-edit-btn');
const originalText = btn.textContent;
btn.textContent = '⏳ 수정 중...';
btn.disabled = true;
setStatus('부분 수정 중...', true);
try {
const response = await fetch('/refine-selection', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
current_html: generatedHTML,
selected_text: selectedText,
request: request,
doc_type: currentDocType
})
});
const data = await response.json();
if (data.error) {
throw new Error(data.error);
}
if (data.success && data.html) {
const frame = document.getElementById('previewFrame');
const doc = frame.contentDocument;
// 간단한 텍스트 교체
const modifiedContent = data.html.replace(/```html\n?/g, '').replace(/```\n?/g, '').trim();
const searchStr = selectedText.substring(0, 30);
const allElements = doc.body.getElementsByTagName('*');
for (const el of allElements) {
if (el.textContent && el.textContent.includes(searchStr)) {
let hasChildWithText = false;
for (const child of el.children) {
if (child.textContent && child.textContent.includes(searchStr)) {
hasChildWithText = true;
break;
}
}
if (!hasChildWithText) {
el.innerHTML = modifiedContent;
break;
}
}
}
generatedHTML = '<!DOCTYPE html>' + doc.documentElement.outerHTML;
// 선택 초기화
selectedText = '';
selectedRange = null;
const aiBtn = document.getElementById('aiEditToolbarBtn');
if (aiBtn) {
aiBtn.classList.remove('has-selection');
aiBtn.title = 'AI 수정 (텍스트를 먼저 선택하세요)';
}
setTimeout(setupIframeSelection, 500);
closeAiEditPopup();
setStatus('부분 수정 완료', true);
}
} catch (error) {
alert('수정 오류: ' + error.message);
setStatus('오류 발생', false);
} finally {
btn.textContent = originalText;
btn.disabled = false;
}
}