Last active
January 29, 2018 18:59
-
-
Save yangtaeho/37046e0eaebc451652aa9f1b6f0f2b72 to your computer and use it in GitHub Desktop.
codeSpitz 74-3 attribute 파서 추가(장황주의)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==== space test ==== | |
let logL = {}; | |
logL.deb = false; | |
logL.inf = false; | |
const attrStrTest = 'class= "test clazz" readonly title=test!! class="test clazz" style= "width : 150px ;height:50px"'; | |
//getAttrList(attrStrTest); | |
const getAttrList = (attrStr) => { | |
const TYPE_KEY = 'KEY'; | |
const TYPE_VALUE = 'VAL'; | |
const attr = JSON.stringify({key:'',value:''}); | |
const itemTemp = JSON.stringify({type:'',value:''}); | |
// ==== base method ======== | |
const setItem = (type,val) => { | |
const item = JSON.parse(itemTemp); | |
item.type = type; | |
item.value = val; | |
return item; | |
}; | |
const setKeyStack = (char,text,stack,cursor) => { | |
const tempCharList = text.split(' '); | |
if(tempCharList.includes("") || tempCharList.length > 1){ | |
const keyList = tempCharList.filter((val)=>{ | |
if(val == '') { | |
return false; | |
} | |
return val; | |
},[]); | |
keyList.map((val)=>{ | |
logL.inf && console.log(cursor,'SET KEY s ====> ', char, val); | |
stack.push(setItem(TYPE_KEY,val)); | |
},stack); | |
} else { | |
logL.inf && console.log(cursor,'SET KEY o ====> ', char, text); | |
stack.push(setItem(TYPE_KEY,text)); | |
//cursor += text; | |
} | |
text = ''; | |
return {char,text,stack,cursor}; | |
}; | |
/** | |
* 제거한 space 갯수만큼 cursor 를 전진시킨다. | |
*/ | |
const getCorrectCursor = (str,cursor) => { | |
if (str[cursor] !== ' ') { | |
//logL.deb && console.log(cursor,'getCorrectCursor throw',str[cursor],str); | |
str = str.substring(cursor,str.length); | |
return {cursor,str}; | |
} | |
for(let i = cursor; cursor < str.length; i++) { | |
//logL.deb && console.log(cursor,'getCorrectCursor befor',str,i,str.length); | |
if (str[i] === ' ') { | |
const tstr = str.substring(i,str.length); | |
//logL.deb && console.log(cursor,'getCorrectCursor ing..',tstr,i); | |
} else { | |
cursor = i; | |
str = str.substring(cursor,str.length); | |
//logL.deb && console.log(cursor,'getCorrectCursor break',str,i); | |
break; | |
} | |
} | |
//logL.deb && console.log(cursor,'getCorrectCursor done',str); | |
return {cursor:cursor,tempT:str}; | |
}; | |
const getAttrVal = (cursor,attrStr,delim) => { | |
//logL.deb && console.log(cursor,'getAttrVal req',attrStr[cursor],delim,"currAttr",attrStr.substring(cursor)); | |
const currAttr = attrStr.substring(cursor+1, cursor = attrStr.indexOf(delim,cursor+1)); | |
//logL.deb && console.log(cursor,'getAttrVal res',attrStr[cursor],delim,currAttr,attrStr.substring(cursor)); | |
return {cursor,currAttr}; | |
}; | |
// ================ | |
const parseKeyValStack = (attrStr) => { | |
let text = ''; | |
let cursor = 0; | |
let stack = []; | |
while (cursor < attrStr.length) { | |
//console.log('attrStr[cursor] : ', attrStr[cursor]); | |
let char = attrStr[cursor]; | |
if (char === '=') { | |
//logL.deb && console.log(cursor,'setKeyStack before', char, text/* , JSON.stringify(stack) */); | |
const v = setKeyStack(char,text,stack,cursor); | |
({char,text,stack,cursor} = v); | |
//logL.deb && console.log(cursor,'setKeyStack after', char, text/* , JSON.stringify(stack) */); | |
let nextChar = attrStr[++cursor]; | |
//logL.deb && console.log(cursor,'get nextChar', nextChar); | |
// 공백인 경우에 대한 처리 | |
var tempT, tempAddCursor; | |
if (nextChar === ' ') { | |
//공백 문자에 대해 커서 당기는 처리 | |
//logL.deb && console.log(cursor,'getCorrectCursor befor',nextChar, attrStr[cursor]); | |
const v = getCorrectCursor(attrStr,cursor); | |
({cursor} = v); | |
nextChar = attrStr[cursor]; | |
//logL.deb && console.log(cursor,'getCorrectCursor after',nextChar, attrStr[cursor]); | |
} | |
if (nextChar === '"' || nextChar === '\'') { | |
//logL.deb && console.log(cursor,'proc. quotation ====> ', char, nextChar, attrStr.substring(cursor, attrStr.length)); | |
const v = getAttrVal(cursor,attrStr,nextChar); | |
const currAttr = v.currAttr; | |
cursor = v.cursor; | |
logL.inf && console.log(cursor,'SET VALUE """ ====> ', char, currAttr); | |
stack.push({type:TYPE_VALUE,value:currAttr}); | |
} else { | |
//logL.deb && console.log(cursor,'proc. no quotation ====> ', char, nextChar, attrStr.substring(cursor, attrStr.length)); | |
const nextCursor = attrStr.indexOf(' ',cursor); | |
const currAttr = attrStr.substring(cursor, nextCursor); | |
cursor = nextCursor; | |
logL.inf && console.log(cursor,'SET VALUE " " ====> ', char, currAttr); | |
stack.push({type:TYPE_VALUE,value:currAttr}); | |
} | |
} else { | |
text += char; | |
} | |
cursor++; | |
} | |
return stack; | |
}; | |
const main = (attrStr) => { | |
let attrs = []; //최종 결과 넣을 곳 | |
const stack = parseKeyValStack(attrStr); | |
//console.log(stack);//logL.debug | |
for (let i = 0, len = stack.length; i < len; i++) { | |
const item = stack[i]; | |
////logL.deb && console.log('최종 파스... item', i, item); | |
let res = JSON.parse(attr); | |
if (item.type == TYPE_VALUE) { | |
console.log('아마도 에러..?'); | |
throw '형이 여기서 왜 나와?'; | |
} | |
if (item.type == TYPE_KEY) { | |
res.key = item.value; | |
const nextItem = stack[i+1]; | |
if (nextItem.type == TYPE_VALUE) { | |
res.value = nextItem.value; | |
i++; | |
} else { | |
res.value = true; //우항이 없는 속성은 true 처리 | |
} | |
} | |
////logL.deb && console.log('최종 파스... res', i, res); | |
attrs.push(res); | |
} | |
logL.deb && console.log("result ============\n",attrs); | |
return attrs; | |
}; | |
return main(attrStr); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==== for main test data ==== | |
const deb = true; //debug | |
const cmd = 'c'; | |
var dat = { | |
a:'<div>test</div>', | |
b:'<div>a<a>b</a>c<img/>d</div>', | |
c:'<div class="test clazz" readonly title=test!! style= "width : 150px ;height:50px">test</div>', | |
d:'<div style="width:150px;height:50px">test<div><img/>a<a>b</a>c<img/>d</div></div>', | |
e:'<div><div>test</div>a<img/>test<div>test2</div><div>test3</div><div>test4</div></div>', | |
}; | |
//class="test clazz" readonly title=test!! style= "width : 150px ;height:50px" | |
// ================================================================================================ | |
//logic | |
const setTextNode = (text,target) => { | |
if (text.legnth) { | |
//어딘가에 삽입.. | |
target.push({type:'TEXT',text}); | |
} | |
}; | |
const parseAttr = (attrStr) => getAttrList(attrStr); //space.js | |
const setElementNode =(input, cursor, text, stack, childrenStacks) => { | |
let isBreak = false; | |
let char = input[cursor++]; | |
if (char === '<') { | |
//시작하는 태그 구간 | |
deb && console.log(cursor,', input[cursor]=',input[cursor]); | |
if (input[cursor] !== '/') { | |
setTextNode(text,stack.tag.children); // 기존 노드 처리.. | |
text = ''; // 새로 시작하므로 리셋 | |
let tagStr = input.substring(cursor, cursor = input.indexOf('>',cursor)); | |
deb && console.log(cursor,', tagStr=',tagStr); | |
const hasAttr = tagStr.indexOf(' ') > -1; | |
let nodeNm = tagStr.substring(0, (hasAttr ? tagStr.indexOf(' ') : tagStr.length)); | |
let attrStr = hasAttr ? tagStr.substring(tagStr.indexOf(' ') + 1, tagStr.length) : ''; | |
let children = []; | |
// 닫힌 태그 처리 <img/> 등 | |
const isClose = input[cursor - 1] == '/'; | |
if (isClose) { | |
nodeNm = nodeNm.substr(0,nodeNm.length - 1); | |
children = null; | |
} | |
deb && console.log(cursor,', hasAttr=',hasAttr); | |
deb && console.log(cursor,', nodeNm=',nodeNm); | |
deb && console.log(cursor,', attrStr=',attrStr); | |
const tag = {name:nodeNm, type:'NODE', attr:parseAttr(attrStr), children:children}; | |
cursor++; | |
stack.tag.children.push(tag); | |
if (!isClose) { | |
childrenStacks.push({tag,back:stack}); //현재 태그를 넣고 돌아갈 태그를 스택에 넣음 | |
isBreak = true; | |
} | |
deb && console.log(cursor,', input[cursor]=',input[cursor]); | |
//let text = input.substring(cursor, input.indexOf('<',cursor)-1); | |
//text = input.substring(cursor, input.indexOf('<',cursor)-1); | |
} else { | |
const stackTagName = stack.tag.name; | |
const currTagName = input.substring(cursor + 1, cursor = input.indexOf('>',cursor)); | |
deb && console.log(cursor, 'stackTagName', stackTagName, 'currTagName', currTagName); | |
if (stackTagName == currTagName) { | |
stack = stack.back; | |
} else { | |
console.log('??'); | |
} | |
deb && console.log(cursor,'end tag ==> input[cursor]=',input[cursor],'text=',text); | |
} | |
} else { | |
text += char; | |
} | |
deb && console.log('==== run result ====\n' ,' cursor=',cursor ,',char=', char ,',text=',text ,'\n========================'); | |
return {cursor, text, stack, isBreak}; | |
}; | |
const parser = input => { | |
const result = {tag:{type:'ROOT',children:[]}}; | |
const childrenStacks = []; | |
let stack = result; | |
let cursor = 0; | |
deb && console.log('==== run start ====\n' | |
,' input=', input | |
,',input.length=', input.length | |
,'\n========================' | |
); | |
do { | |
let text = ''; | |
while (cursor < input.length) { | |
const ele = setElementNode(input, cursor, text, stack, childrenStacks); | |
({cursor, text, stack} = ele); | |
if(ele.isBreak) { | |
break; | |
} | |
} | |
} while (stack = childrenStacks.pop()); | |
return result; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<script src="attribute-parser.js"></script> | |
<script src="code.js"></script> | |
</head> | |
<body> | |
<div id="te"> | |
</div> | |
<script> | |
function log(title,data){ | |
const res = ` | |
${JSON.stringify(data)} | |
`; | |
const brEle = document.createElement('BR'); | |
document.getElementById('te').append('==== html ===='); | |
document.getElementById('te').append(brEle.cloneNode()); | |
document.getElementById('te').append(title); | |
document.getElementById('te').append(brEle.cloneNode()); | |
document.getElementById('te').append('==== res ===='); | |
document.getElementById('te').append(brEle.cloneNode()); | |
document.getElementById('te').append(res); | |
document.getElementById('te').append(brEle.cloneNode()); | |
document.getElementById('te').append(brEle.cloneNode()); | |
}; | |
function main(cmd){ | |
document.getElementById('te').innerHTML = ''; | |
if (cmd) { | |
log(dat[cmd],parser(dat[cmd])); | |
} else { | |
log(dat['a'],parser(dat['a'])); | |
log(dat['b'],parser(dat['b'])); | |
log(dat['c'],parser(dat['c'])); | |
log(dat['d'],parser(dat['d'])); | |
log(dat['e'],parser(dat['e'])); | |
} | |
} | |
main(cmd); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment