feat(ui): 인라인 구분자 지원 및 리스트 자료형 제거
- VALUE_TYPES에서 '리스트 (List)' 제거 - SEP_CFG에 '줄바꿈' 프리셋 추가 (없음/줄바꿈/빈줄) - toText() 재작성: lines 배열 → string 직접 결합 방식으로 변경 - 인라인 구분자(예: '/') 사용 시 a/b/c 형태로 한 줄 출력 - ss() 함수: none='' / newline='\n' / blank='\n\n' / 직접입력=그대로 - pendingSep 패턴으로 연속 child node 간 구분자 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -230,7 +230,6 @@ input,textarea,button,select{font-family:inherit}
|
||||
// 상수
|
||||
// ════════════════════════════════════════════════════════
|
||||
const VALUE_TYPES = [
|
||||
{v:'list', lbl:'리스트 (List)'},
|
||||
{v:'node', lbl:'노드 (Node)'},
|
||||
{v:'string', lbl:'문자열 (String)'},
|
||||
{v:'integer', lbl:'정수 (Integer)'},
|
||||
@@ -631,8 +630,9 @@ function renderValue(nid, val){
|
||||
}
|
||||
|
||||
const SEP_CFG = [
|
||||
{v:'none', lbl:'없음'},
|
||||
{v:'blank', lbl:'빈 줄'},
|
||||
{v:'none', lbl:'없음'},
|
||||
{v:'newline', lbl:'줄바꿈'},
|
||||
{v:'blank', lbl:'빈 줄'},
|
||||
];
|
||||
|
||||
function setSep(nid, field, val){
|
||||
@@ -712,49 +712,63 @@ function renderSetting(nid, key, val){
|
||||
function parseNames(raw){ return (raw??'').trim().split(/[\s,\n]+/).filter(Boolean) }
|
||||
|
||||
function toText(){
|
||||
const lines=[];
|
||||
const title=S.title.trim();
|
||||
if(title){ lines.push(`${S.titleMark}${title}`); lines.push(''); }
|
||||
|
||||
function applySep(sep){
|
||||
// 구분자 값 → 실제 문자열
|
||||
function ss(sep){
|
||||
const s=sep??'blank';
|
||||
if(s==='none') return;
|
||||
if(s==='blank'){ lines.push(''); return; }
|
||||
for(const l of String(s).replace(/\\n/g,'\n').split('\n')) lines.push(l);
|
||||
if(s==='none') return '';
|
||||
if(s==='newline') return '\n';
|
||||
if(s==='blank') return '\n\n';
|
||||
return String(s); // 직접 입력값 (예: '/', ', ')
|
||||
}
|
||||
|
||||
// 노드 하나를 문자열로 렌더링
|
||||
function rNode(node){
|
||||
lines.push(`${node.mark??''}${node.content||''}`);
|
||||
let t=`${node.mark??''}${node.content||''}`;
|
||||
let pendingSep=null; // 다음 child node 앞에 붙일 구분자
|
||||
let prevWasList=false;
|
||||
|
||||
for(let i=0;i<node.values.length;i++){
|
||||
const v=node.values[i];
|
||||
const nextV=node.values[i+1]??null;
|
||||
|
||||
if(v.type==='list'){
|
||||
const ns=parseNames(v.names); if(!ns.length) continue;
|
||||
const cat=(v.category??'').trim(), pre=cat?`(${cat}) `:'';
|
||||
const sep=v.sep??' ', npl=v.namesPerLine??0;
|
||||
if(sep==='\n') ns.forEach((n,j)=>lines.push((j===0?pre:'')+n));
|
||||
else if(npl>0) for(let j=0;j<ns.length;j+=npl) lines.push((j===0?pre:'')+ns.slice(j,j+npl).join(sep));
|
||||
else lines.push(pre+ns.join(sep));
|
||||
lines.push(''); // list 뒤 빈 줄 (항상)
|
||||
const lsep=v.sep??' ', npl=v.namesPerLine??0;
|
||||
let lt;
|
||||
if(lsep==='\n') lt=ns.map((n,j)=>(j===0?pre:'')+n).join('\n');
|
||||
else if(npl>0) lt=Array.from({length:Math.ceil(ns.length/npl)},(_,j)=>(j===0?pre:'')+ns.slice(j*npl,(j+1)*npl).join(lsep)).join('\n');
|
||||
else lt=pre+ns.join(lsep);
|
||||
t+='\n'+lt+'\n'; // list는 항상 줄 단위
|
||||
prevWasList=true;
|
||||
pendingSep=null;
|
||||
|
||||
} else if(v.type==='node'){
|
||||
if(!prevWasList) applySep(node.childSep); // list가 없을 때만 childSep 적용
|
||||
rNode(v.node);
|
||||
if(nextV&&nextV.type==='node') applySep(v.node.nextSep); // 다음도 노드면 nextSep
|
||||
// 이 child node 앞에 붙일 구분자 결정
|
||||
if(!prevWasList){
|
||||
t+=(pendingSep!==null) ? pendingSep : ss(node.childSep??'blank');
|
||||
}
|
||||
t+=rNode(v.node);
|
||||
prevWasList=false;
|
||||
// 다음 형제가 노드면 nextSep을 예약
|
||||
pendingSep=(nextV&&nextV.type==='node') ? ss(v.node.nextSep??'blank') : null;
|
||||
|
||||
} else {
|
||||
if(v.data) lines.push(String(v.data));
|
||||
if(v.data) t+='\n'+String(v.data);
|
||||
prevWasList=false;
|
||||
pendingSep=null;
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
const title=S.title.trim();
|
||||
let out=title?`${S.titleMark}${title}\n\n`:'';
|
||||
for(let i=0;i<S.nodes.length;i++){
|
||||
rNode(S.nodes[i]);
|
||||
if(i<S.nodes.length-1) applySep(S.nodes[i].nextSep);
|
||||
out+=rNode(S.nodes[i]);
|
||||
if(i<S.nodes.length-1) out+=ss(S.nodes[i].nextSep??'blank');
|
||||
}
|
||||
return lines.join('\n').replace(/\n{3,}/g,'\n\n').trimEnd()+'\n';
|
||||
return out.replace(/\n{3,}/g,'\n\n').trimEnd()+'\n';
|
||||
}
|
||||
|
||||
// ════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user