You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The errors were
! Failed to parse doc tags /blah/blah/dom.js: Cannot read property '1' of null
TypeError: Cannot read property '1' of null
at Object.module.exports.DOC_TAGS.return.parseValue (/home/elisa/repos/others/winternote/node_modules/groc/lib/doc_tags.coffee:180:23)
at Object.module.exports.Utils.parseDocTags (/home/elisa/repos/others/winternote/node_modules/groc/lib/utils.coffee:472:41)
at Default.module.exports.Base.renderFile (/home/elisa/repos/others/winternote/node_modules/groc/lib/styles/base.coffee:31:20)
at /home/elisa/repos/others/winternote/node_modules/groc/lib/project.coffee:74:24
at fs.js:266:14
at Object.oncomplete (fs.js:107:15)
The content of dom.js is shown below.
"use strict";
// > # [Document Object Model](https://developer.mozilla.org/en-US/docs/DOM/About_the_Document_Object_Model)
define('dom', ['underscore', 'iter', 'assert'], function(_, iter, assert) {
/* ------------------------------------------------------------------------------- */
// dom predicate
// ### isBlock
// > 크기를 갖는 컨테이너 여부 리턴 ex) P, DIV, IMG(float)
// > [HTML Display property](http://www.w3schools.com/cssref/pr_class_display.asp)
var isBlock = function(el) {
if (el && (isBodyContainer(el) || isPara(el) || isList(el) || isHR(el) || isDiv(el) || isTable(el)) ) {
return true;
}
if (el && el.style && el.style["float"] && el.style["float"] !== '' && el.style["float"] !== 'none'
|| (el && el.style && el.style.cssText && el.style.cssText.toLowerCase().indexOf('float') > -1)) {
return true;
}
return false;
};
// ### isTable
// > 테이블 여부 판단
var isTable = function(el) {
return el && el.nodeName === "TABLE";
};
// ### isTBody
// > TBody 여부 판단
var isTBody = function(el) {
return el && el.nodeName === "TBODY";
};
// ### isTHead
// > THead 여부 판단
var isTHead = function(el) {
return el && el.nodeName === "THEAD";
};
// ### isTR
// > TR 여부 판단
// * `el` HTMLElement -> bool
var isTR = function(el) {
return el && el.nodeName === 'TR';
};
// ### isTD
// > TD 여부 판단
// * `el` HTMLElement -> bool
var isTD = function(el) {
return el && el.nodeName === 'TD';
};
// ### isCell
// > 테이블셀 여부 판단
// * `el` HTMLElement -> bool
var isCell = function(el) {
return el && (el.nodeName === 'TD' || el.nodeName === 'TH');
};
// ### isContainer
// > 컨테이너 객체 여부 판단: 다른 객체(UL, DIV 등)을 담을 수 있는 객체
var isContainer = function(el) {
return !isData(el);
};
// ### isFirstContainerChild
// > 부모의 첫번째 컨테이너 객체인지 여부 판단
var isFirstContainerChild = function(el) {
var aChild = _.filter(_.map(el.parentNode.childNodes), isContainer);
return aChild.length > 0 && _.first(aChild) === el;
};
// ### isLastContainerChild
// > 부모의 마지막 컨테이너 객체인지 여부 판단
var isLastContainerChild = function(el) {
var aChild = _.filter(_.map(el.parentNode.childNodes), isContainer);
return aChild.length > 0 && _.last(aChild) === el;
};
// ###isDataBlock
// > hr이나 float된 image등 커서가 위치할 수 있는 객체
var isDataBlock = function(el) {
return isHR(el) || isIMG(el) || isBR(el);
};
// ###isDocumentFragment
var isDocumentFragment = function(el) {
return el && el.nodeName === "#document-fragment";
};
// ### isInlineContainer
// > 인라인을 가질 수 있는 노드 여부 판단
var isInlineContainer = function(el) {
return isPara(el) || isBodyContainer(el) || isDocumentFragment(el) || isNoteEditable(el);
};
// ### isIMG
// > 이미지 노드 여부 판단
var isIMG = function(el) {
return el && el.nodeName === "IMG";
};
// ### isData
// > 인라인 노드 여부 판단
var isData = function(el) {
return el && (el.nodeName === "#text" ||
el.nodeName === "IMG" ||
el.nodeName === "HR" ||
el.nodeName === "INPUT" ||
el.nodeName === "BR") ;
};
// ### isText
// > 텍스트 노드 여부 판단
var isText = function(el) {
return el && (el.nodeName === "#text");
};
var isFont = function(el) {
return el && (el.nodeName === "FONT");
};
var isStrike = function(el) {
return el && (el.nodeName === "STRIKE" || el.nodeName === "S" || el.nodeName === "DEL");
};
var isBold = function(el) {
return el && (el.nodeName === "BOLD" || el.nodeName === "B" || el.nodeName === "STRONG");
};
var isItalic = function(el) {
return el && (el.nodeName === "ITALIC" || el.nodeName === "I");
};
var isUnderline = function(el) {
return el && (el.nodeName === "UNDERLINE" || el.nodeName === "U");
};
var isDiv = function(el) {
return el && el.nodeName === "DIV";
};
var isBlockquote = function(el) {
return el && el.nodeName === "BLOCKQUOTE";
};
var isNoteEditor = function(el){
return el && $(el).hasClass('note-editor');
};
var isNoteEditable = function(el){
return el && $(el).hasClass('note-editable');
};
var isFirstParaTextnode = function(el) {
var elPara = ancestor(el, function(el){ return isPara(el) || isCell(el); });
if (!elPara) { return false; }
var aAncestor = _.reject(listAncestor(elPara), isCell);
return _.all(aAncestor, isFirstContainerChild);
};
var isLastParaTextnode = function(el) {
var elPara = ancestor(el, function(el){ return isPara(el) || isCell(el); });
if (!elPara) { return false; }
var aAncestor = _.reject(listAncestor(elPara), isCell);
return _.all(aAncestor, isLastContainerChild);
};
var isBodyContainer = function(el) {
return isNoteEditable(el) || isCell(el) || isTR(el) || isTD(el) || isBlockquote(el) || isTHead(el) || isTBody(el) || isDiv(el);
};
// ### isEdgeOf
// > 입력 받은 위치의 구석(왼쪽 혹은 오른쪽 위치) 여부 리턴
var isEdgeOf = function(el, offset) {
if (isEmpty(el)) { return true; }
return offset === 0 || length(el) === offset;
};
// ### isLeftEdge
// > 입력 받은 위치의 왼쪽구석 여부 리턴
var isLeftEdge = function(el, offset) {
return offset === 0;
};
// ### isRightEdge
// > 입력 받은 위치의 오른쪽구석 여부 리턴
var isRightEdge = function(el, offset) {
return offset === length(el);
};
// ### isLeftEdgeOf
// > 입력 받은 위치의 root로 부터의 왼쪽구석 여부 리턴
var isLeftEdgeOf = function(elRoot, el) {
while (el && el !== elRoot) {
if (position(el) !== 0) { return false; }
el = el.parentNode;
}
assert.ok(el !== null); // el이 root에 포함되지 않는 경우...
return true;
};
// ### isRightEdgeOf
// > 입력 받은 위치의 root로 부터의 오른쪽구석 여부 리턴
var isRightEdgeOf = function(elRoot, el) {
while (el && el !== elRoot) {
if (position(el) !== length(el.parentNode)-1) { return false; }
el = el.parentNode;
}
assert.ok(el !== null); // el이 root에 포함되지 않는 경우...
return true;
};
// ### isEmpty
// > 노드가 비어 있는 노드인지 판단
var isEmpty = function(el) {
if (isData(el)) {
return false;
}
return el.childNodes.length === 0;
};
// ### isSiblingOf
// > elSrc 가 elTarget에 형재 노드인지 검사
var isSiblingOf = function(elSrc, elTarget) {
var aChild = elSrc.parentNode.childNodes;
for (var i=0, len=aChild.length; i < len; i++) {
if (aChild[i] === elTarget) {
return true;
}
}
return false;
};
// ### contains
// > elSrc가 elParent에 자식 여부인지 판단
var contains = function(elSrc, elParent) {
return !!ancestor(elSrc, function(el) {
return el === elParent;
});
};
// ### isAdjacent
// > 인접노드 여부 리턴
var isAdjacent = function(elA, elB) {
return elA.nextSibling === elB || elB.nextSibling === elA;
};
// ### isNBSP
// > non breakable space 판단
var isNBSP = function(el) {
return isText(el) && NBSP === el.nodeValue;
};
// ### isFEFF
// > no width non breakable space 판단
var isFEFF = function(el) {
return isText(el) && FEFF === el.nodeValue;
};
// ### isHeading
// > 머리글여부 리턴
// * `el` HTMLElement -> bool
var isHeading = function(el) {
return el && /^H[1-7]/.test(el.nodeName);
};
// ### isPara
// > 문단 여부 판단
// * `el` HTMLElement -> bool
var isPara = function(el) {
return el && (/^P|^LI/.test(el.nodeName) || /^H[1-7]/.test(el.nodeName));
};
// ### isPurePara
// > 리스트가 아닌 순수한 문단
var isPurePara = function(el) {
return isPara(el) && !isLI(el);
};
// ### isList
// > 리스트 여부 판단
// * `el` HTMLElement -> bool
var isList = function(el) {
return el && (el.nodeName === 'UL' || el.nodeName === 'OL');
};
// ### isOrderedList
// > 순서가 있는 리스트 여부 판단
// * `el` HTMLElement -> bool
var isOrderedList = function(el) {
return el && el.nodeName === 'OL';
};
// ### isUnorderedList
// > 순서가 없는 리스트 여부 판단
// * `el` HTMLElement -> bool
var isUnorderedList = function(el) {
return el && el.nodeName === 'UL';
};
// ### isBullet
// > ul/ol여부 판단
var isBullet = function(el) {
return isOrderedList(el) || isUnorderedList(el);
};
// ### isLI
// > LI 여부 리턴
var isLI = function(el) {
return el && el.nodeName === 'LI';
};
// ### isP
// > P 여부 리턴
var isP = function(el) {
return el && el.nodeName === 'P';
};
// ### isA
// > A 여부 리턴
var isA = function(el) {
return el && el.nodeName === 'A';
};
// ### isHR
// > HorizontalRule 여부 판단
// * `el` HTMLElement -> bool
var isHR = function(el) {
return el && el.nodeName === 'HR';
};
// ### isBR
// * `el` HTMLElement -> bool
var isBR = function(el) {
return el && el.nodeName === 'BR';
};
// ### isEmptyText
// > 빈 텍스트 엘리먼트 여부 리턴
var isEmptyText = function(el) {
return isText(el) && (el.nodeValue === '');
};
// ### isEmptyPara
// > 빈 문단 여부 리턴
var isEmptyPara = function(el) {
if (!isPara(el)) { return false; }
var aElInline = descendants(el, isData);
return aElInline.length === 0 ||
(aElInline.length === 1 && isNBSP(aElInline[0])) ||
(aElInline.length === 1 && isFEFF(aElInline[0]));
};
// ### isEmptyInlineContainer
// > 빈 컨테이너 여부 리턴
var isEmptyInlineContainer = function(el) {
if (isEmptyPara(el)) { return true; }
if (!isInlineContainer(el)) { return false; }
var aElInline = descendants(el, isData);
return aElInline.length === 0 ||
(aElInline.length === 1 && isNBSP(aElInline[0])) ||
(aElInline.length === 1 && isFEFF(aElInline[0]));
};
// ### isP
// > SPAN 여부 리턴
var isSpan = function(el) {
return el && el.nodeName === 'SPAN';
};
// ### isInvisible
// > 보이지 않는 노드 여부 판단
var isInvisible = function(el) {
var aElInline = descendants(el, isData);
return aElInline.length === 0;
};
// ### isOnContentEditable
// > 편집영역 위에 있는 노드 여부 판단
var isOnContentEditable = function(el) {
while (el) {
if (isNoteEditable(el)) { return true; }
el = el.parentNode;
}
return false;
};
/* ------------------------------------------------------------------------------- */
// dom modifier
// ### slice
// > dom 트레버싱
// > `fApply` 각 노드에 적용할 함수
// > `fPred` 노드 탐색을 어느 시점에 멈출지 판단 | optional
var _traverse = function(el, fBefore, fAfter, fStop, bRtoL) {
try {
var trav = function(el) {
if (fStop && fStop(el)) { throw "break"; }
if (fBefore) { fBefore(el); }
var aChild = bRtoL ? _.toArray(el.childNodes).reverse() : _.toArray(el.childNodes);
for (var i=0, len=aChild.length; i < len; i++ ) { trav(aChild[i]); }
if (fAfter) { fAfter(el); }
};
trav(el);
} catch(e) {
if (e !== "break") { throw e; }
}
};
// ### traverse
// 좌측 구석 -> 상향 탐색
var traverse = function(el, fApply, fStop) {
_traverse(el, null, fApply, fStop);
};
// ### traverseInt
// 좌측 구석으로 하향탐색
var traverseIn = function(el, fApply, fStop) {
_traverse(el, fApply, null, fStop);
};
// ### traverseRight
// 우측 구석 -> 상향탐색
var traverseRight = function(el, fApply, fPred) {
_traverse(el, null, fApply, fPred, true);
};
// ### traverseRightIn
// 우측 구석으로 하향 탐색
var traverseRightIn = function(el, fApply, fPred) {
_traverse(el, fApply, null, fPred, true);
};
// ### descendants
// > el 밑에 자식 노드 중에 fPred를 만족하는 모든 노드를 반환
var descendants = function(el, fPred) {
fPred = fPred || iter.success;
var aElDescendant = [];
traverse(el, function(elDescendant) {
if (fPred(elDescendant)) {
aElDescendant.push(elDescendant);
}
});
return aElDescendant;
};
// ### hasDescendants
// > 자식 노드중 pred를 만족하는지 여부 판단
var hasDescendants = function(el, pred) {
return descendants(el, pred).length > 0;
};
// ### hasParent
// > 부모 노드가 있는지 여부 판단
var hasParent = function(el) {
return el.parentNode;
};
// ### hasNext
// > 다음 형제 노드가 있는지 검사
var hasNext = function(el) {
return el && el.nextSibling;
};
// ### hasPrev
// > 이전 형제 노드가 있는지 검사
var hasPrev = function(el) {
return el && el.previousSibling;
};
// ### hasChild
// > 자식 노드 존재하는지 여부 검사
var hasChild = function(el) {
return el && el.childNodes && el.childNodes.length > 0;
};
// ### ancestor
// > pred에 일치하는 가장 가까운 부모 노드 찾기
// > 자신을 포함해서 찾는다.
// TODO: note-editable을 사용하지 않는 버전 필요
var ancestor = function(el, pred) {
var elCurrent = el;
while (elCurrent) {
if (!elCurrent || elCurrent.className === 'note-editable') { break; }
if (pred(elCurrent)) { return elCurrent; }
elCurrent = elCurrent.parentNode;
}
return null;
};
// ### lastAncestor
// > pred에 일치하는 최상위 부모노드 찾기
var lastAncestor = function(el, pred) {
var aAncestor = listAncestor(el);
return _.last(_.filter(aAncestor, pred));
};
// ### listAncestor
// > ancestor 목록 리턴(가까운 Ancestor부터)
var listAncestor = function(el, pred) {
pred = pred || iter.fail;
var aElVisited = [];
ancestor(el, function(e) {
aElVisited.push(e);
return pred(e);
});
return aElVisited;
};
// ### commonAncestor
// > commonAncestor 반환
var commonAncestor = function(node1, node2) {
var ancestors = [], n;
for (n = node1; n; n = n.parentNode) {
ancestors.push(n);
}
for (n = node2; n; n = n.parentNode) {
if (_.contains(ancestors, n)) {
return n;
}
}
return null;
};
var getClosestAncestorIn = function(node, ancestor, selfIsAncestor) {
var p, n = selfIsAncestor ? node : node.parentNode;
while (n) {
p = n.parentNode;
if (p === ancestor) {
return n;
}
n = p;
}
return null;
};
var comparePoints = function(nodeA, offsetA, nodeB, offsetB) {
// See http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Comparing
var nodeC, root, childA, childB, n;
if (nodeA == nodeB) {
// Case 1: nodes are the same
return offsetA === offsetB ? 0 : (offsetA < offsetB) ? -1 : 1;
} else if ( (nodeC = getClosestAncestorIn(nodeB, nodeA, true)) ) {
// Case 2: node C (container B or an ancestor) is a child node of A
return offsetA <= position(nodeC) ? -1 : 1;
} else if ( (nodeC = getClosestAncestorIn(nodeA, nodeB, true)) ) {
// Case 3: node C (container A or an ancestor) is a child node of B
return position(nodeC) < offsetB ? -1 : 1;
} else {
// Case 4: containers are siblings or descendants of siblings
root = commonAncestor(nodeA, nodeB);
childA = (nodeA === root) ? root : getClosestAncestorIn(nodeA, root, true);
childB = (nodeB === root) ? root : getClosestAncestorIn(nodeB, root, true);
if (childA === childB) {
// This shouldn't be possible
throw "comparePoints got to case 4 and childA and childB are the same!";
} else {
n = root.firstChild;
while (n) {
if (n === childA) {
return -1;
} else if (n === childB) {
return 1;
}
n = n.nextSibling;
}
}
}
};
// ### comparePositions
// > 입력받은 posA, posB을 비교
// > @return number 0: equal to,
// > -1: posA less than posB,
// > 1: posA greater than posB
var comparePositions = function(posA, posB) {
return comparePoints(posA.cont, posA.offset, posB.cont, posB.offset);
};
// ### leftBottom
// > 가장 왼쪽 노드 찾아가서 반환
var leftBottom = function(el) {
return el.firstChild ? leftBottom(el.firstChild) : el;
};
// ### inlineTop
// Block에 가장 가까운 Inline 노드를 반환
var inlineTop = function(el) {
return _.last(listAncestor(el, function(e) { return isBlock(e.parentNode); }));
};
// ### styleInlineTop
// Block에 가장 가까운 style 가능한 Inline 노드를 반환
var styleInlineTop = function(el) {
return _.last(listAncestor(el, function(e) { return isA(e.parentNode) || isBlock(e.parentNode); }));
};
// ### closetBody
// > 가장 가까운 bodyContainer를 반환
var closetBody = function(el) {
var elCurrent = el;
while (elCurrent) {
if (isBodyContainer(elCurrent)) {
return elCurrent;
}
elCurrent = elCurrent.parentNode;
}
};
// ### length
// > 입력받은 엘리먼트의 자식노드의 수 반환
// > 텍스트 노드의 경우 글자 수 반환
var length = function(el) {
assert.ok(el);
if (isData(el)) {
return isText(el) ? el.nodeValue.length : 1;
}
switch (el.nodeType) {
case 7:
case 10:
return 0;
case 3:
case 8:
return el.length;
default:
return el.childNodes.length;
}
};
// ### position
// > 현재 노드 위치를 반환
var position = function (el) {
var cnt = 0;
for (var i=0; el = el.previousSibling; i++) {}
return i;
};
// ### depth
// > 현재 노드에 depth를 반환
var depth = function(el, pred) {
pred = pred || iter.fail;
return listAncestor(el, pred).length;
};
// ### remove
// > node el을 dom 에서 삭제
var remove = function(el) {
removeNode(el, true);
};
// ### removeNode
// > elNode를 dom 상에서 제거 [removeNode](http://help.dottoro.com/ljxjnsic.php)
// > `bRemoveChild` child node 제거 여부, true인 경우 자식 노드를 모두 제거한다
var removeNode = function(elNode, bRemoveChild) {
if (!elNode || !elNode.parentNode) { return; }
if (elNode.removeNode) { elNode.removeNode(bRemoveChild); return; }
var elParent = elNode.parentNode;
if (!bRemoveChild) {
var aNode = [], i, len;
for (i=0; i < elNode.childNodes.length; i++) {
aNode.push(elNode.childNodes[i]);
}
for (i=0, len=aNode.length; i el 이 빈 노드인 경우 dom 상에서 제거한다.
// > 재귀적으로 상위 노드를 계속 탐색한다
var removeWhile = function(el, pred) {
assert.ok(el);
var walk = function(el) {
var elParent = el.parentNode;
if (elParent && pred(el)) {
elParent.removeChild(el);
walk(elParent, pred);
}
};
var elParent = el.parentNode;
remove(el);
walk(elParent);
};
// ### removeAllAttributes
// > element의 모든 속성 제거
var removeAllAttributes = function(el, excludePred) {
_.each(_.toArray(el.attributes), function(attr) {
if (!attr) { return; }
if (excludePred && excludePred(attr.name)) return;
el.removeAttribute(attr.name);
});
};
var NBSP = String.fromCharCode(160);
var FEFF = "\ufeff";
var BASE_PARA_HTML = '
'+FEFF+'
';
// appends: append children
var appends = function(node, aChild) {
_.each(aChild, function(child) {
node.appendChild(child);
});
};
// ### split
// > `elRoot` : 잘라낼 트리 루트
// > `elPivot` : 잘라낼 기준 노드
// > `offset` : 텍스트 노드인 경우 잘라낼 offset
var splitTree = function(root, pivot, offset) {
assert.ok(root); assert.ok(pivot);
// split pivot
var splitPivot = function(current, offset) {
if (offset >= length(current)) { return current.nextSibling; }
if (offset === 0) { return current; }
// splitText
if (isText(current)) { return current.splitText(offset); }
// splitNode
var child = current.childNodes[offset];
current = insertAfter(current.cloneNode(false), current);
appends(current, listNext(child, iter.fail));
return current;
};
var aAncestor = listAncestor(pivot, iter.eq(root));
if (aAncestor.length === 1) {
return splitPivot(pivot, offset);
}
return _.reduce(_.tail(aAncestor), function(current, parent) {
var parentClone = insertAfter(parent.cloneNode(false), parent);
if (current === pivot) {
current = splitPivot(current, offset);
}
appends(parentClone, listNext(current, iter.fail));
return parentClone;
}, pivot);
};
// Note that we cannot use splitText() because it is bugridden in IE 9.
var splitDataNode = function(node, index, positionsToPreserve) {
var newNode = node.cloneNode(false);
newNode.deleteData(0, index);
node.deleteData(index, node.length - index);
insertAfter(newNode, node);
// Preserve positions
if (positionsToPreserve) {
for (var i = 0, position; position = positionsToPreserve[i++]; ) {
// Handle case where position was inside the portion of node after the split point
if (position.node == node && position.offset > index) {
position.node = newNode;
position.offset -= index;
}
// Handle the case where the position is a node offset within node's parent
else if (position.node == node.parentNode && position.offset > position(node)) {
++position.offset;
}
}
}
return newNode;
};
// ### splitText
// > 텍스트 노드를 반환
var splitText = function(el, offset) {
if (offset === 0) {
return el;
} else if (length(el) === offset) {
return null;
} else {
return splitDataNode(el, offset);
}
};
// ### insertBefore
// > elNew를 elTarget 이전에 삽입
var insertBefore = function(elNew, elTarget) {
return elTarget.parentNode.insertBefore(elNew, elTarget);
};
// ### insertAfter
// > elNew를 elTarget 이후에 삽입
var insertAfter = function(node, precedingNode) {
var nextNode = precedingNode.nextSibling, parent = precedingNode.parentNode;
if (nextNode) {
parent.insertBefore(node, nextNode);
} else {
parent.appendChild(node);
}
return node;
};
// ### replace
// > 입력받은 노드의 nodeName을 변경
// > ! 원본은 삭제
var replace = function(el, sNodeName) {
assert.ok(el && sNodeName);
var elNew = document.createElement(sNodeName);
var sStyle = el.style.cssText;
if (sStyle) {
elNew.style.cssText = sStyle;
}
if (hasChild(el)) {
_.each(_.toArray(el.childNodes), function(elChild) {
elNew.appendChild(elChild);
});
}
insertAfter(elNew, el);
removeNode(el);
return elNew;
};
// ### clone
// 노드를 복제
// > !ie8 에서 잘라진 텍스트 노드를 normalize 해버리는 문제가 있다.
var clone = function(el) {
if (!el) { return; }
if (el.childNodes) { // IE8에서 textNode가 병합되는 문제 회피
var elClone = el.cloneNode(false);
_.each(el.childNodes, function(elChild){
elClone.appendChild(elChild.cloneNode(true));
});
return elClone;
} else {
return el.cloneNode(true);
}
};
// ### parent
// > 노드에 부모 노드 반환
var parent = function(el) {
var elParent = el.parentNode;
if (elParent.className === 'note-editable') { return null; }
return elParent;
};
// ### next
// > 다음 형제 노드 찾기
var next = function(el, pred) {
var elNext = el;
while (elNext) {
if (pred(elNext)) { return elNext; }
elNext = elNext.nextSibling;
}
return null;
};
// ### listNext
// > 다음 형제 노드를 pred가 만족할 때 까지 acc, 자신을 포함
var listNext = function(el, pred) {
var aNode = [], elNext = el;
while (elNext) {
if (pred(elNext)) { break; }
aNode.push(elNext);
elNext = elNext.nextSibling;
}
return aNode;
};
// ### listPrev
// > 이전 형제 노드를 pred가 만족할 때 까지 acc, 자신을 포함
var listPrev = function(el, pred) {
var aNode = [], elPrev = el;
while (elPrev) {
if (pred(elPrev)) { break; }
aNode.push(elPrev);
elPrev = elPrev.previousSibling;
}
return aNode;
};
// ### nodesBetween
// > start, end 사이에 노드를 모두 가지고 온다
var nodesBetween = function(elStart, elEnd) {
if (elStart === elEnd) { return [elStart]; }
var elCommon = commonAncestor(elStart, elEnd);
var elEndAncestor = ancestor(elEnd, iter.peq('parentNode', elCommon));
var aNode = [], bFlag = false;
traverse(elCommon, function(el) {
if (el === elStart) { bFlag = true; }
if (bFlag) { aNode.push(el); }
}, iter.eq(elEndAncestor));
var aEnd = [];
traverseIn(elEndAncestor, iter.push(aEnd), iter.eq(elEnd));
aEnd.push(elEnd);
return aNode.concat(aEnd);
};
// ### nextBP
var nextBP = function(bpInit) {
var elCont = bpInit.node, offset = bpInit.offset;
if (length(elCont) === offset) {
if (elCont.className === 'note-editable') { return null; }
return {node: elCont.parentNode, offset: position(elCont) + 1};
} else {
if (hasChild(elCont)) {
var elChild = elCont.childNodes[offset];
return {node: elChild, offset: 0};
} else {
return {node: elCont, offset: offset + 1};
}
}
};
// ### prevBP
var prevBP = function(bpInit) {
var elCont = bpInit.node, offset = bpInit.offset;
if (offset === 0) {
if (elCont.className === 'note-editable') { return null; }
return {node: elCont.parentNode, offset: position(elCont)};
} else {
if (hasChild(elCont)) {
var elChild = elCont.childNodes[offset - 1];
return {node: elChild, offset: length(elChild)};
} else {
return {node: elCont, offset: offset - 1};
}
}
};
// ### makeUntil
var makeUntil = function(fnUnit) {
return function(pred) {
var stack = [], item = fnUnit.call(this);
while (item) {
if (pred(item, stack)) { return item; }
stack.push(item);
item = fnUnit.call(item);
}
};
};
// ### makeOffsetPath
// > BPPath를 리턴
var makeOffsetPath = function(elRoot, elPivot) {
var aOffset = [], el = elPivot;
while (el && el !== elRoot) {
aOffset.push(position(el));
el = el.parentNode;
}
assert.ok(el !== null); // el이 root에 포함되지 않는 경우...
aOffset.push(position(elRoot));
return aOffset.reverse();
};
// ### fromOffsetPath
// > elRoot와 aOffset을 받아 특정 노드를 리턴
var fromOffsetPath = function(elRoot, aOffset) {
assert.ok(elRoot && aOffset);
aOffset = _.rest(aOffset);
var el = elRoot;
_.each(aOffset, function(offset) {
el = el.childNodes[offset];
});
return el;
};
// ### create
// > dom 노드 생성
var create = function(sTagName) {
assert.ok(sTagName);
return document.createElement(sTagName);
};
// ### fragment
// > html 을 받아서 documentFrgment를 반환
var fragment = function(sHTML) {
var frag = document.createDocumentFragment();
if (!sHTML) { return frag; }
var elTemp = document.createElement("DIV");
elTemp.innerHTML = sHTML;
_.each(_.toArray(elTemp.childNodes), function(el) {
frag.appendChild(el);
});
return frag;
};
// ### element
// > shtml을 받아서 element를 반환
// ! shtml은 루트에 요소가 하나여야 한다
// ex) true ==
,
// ex) false ==
var element = function(sHTML) {
var elFrag = fragment(sHTML);
assert.ok(elFrag.childNodes.length === 1);
return elFrag.firstChild;
};
// ### text
var text = function(el) {
var elDiv = create("div");
elDiv.appendChild(clone(el));
return elDiv.textContent || elDiv.innerText ;
};
// ### wrap
var wrap = function(sTag, el) {
var elWrap = create(sTag);
insertBefore(elWrap, el);
elWrap.appendChild(el);
return elWrap;
};
// ### stripTagSpace
// > HTML 태그 사이에 공백을 제거한다
var stripTagSpace = function(sText) {
// 중복되는 정규식이 있어보임
return sText.replace(/\r?\n?/g, "") // 뉴라인 제거
.replace(/>([ \t]+)<') // 태그 사이 공백 제거
.replace(/[ \t][ \t]+/g, " ") // 2개 이상 공백을 1개로 변경
.replace(/^[ \t]+|[ \t]+$/, ""); // 공백으로 시작하거나 공백으로 끝나는 부분 제거
};
// ### stripFEFF
// > 모든 FEFF를 제거 공백을 제거한다
var stripFEFF = function(sText) {
// 중복되는 정규식이 있어보임
return sText.replace(/\ufeff/g, ""); // FEFF 제거
};
// ### repairHTML
// > HTML 태그 보정
var repairHTML = function(sHTML) {
// '>'짝이 맞지 않는 html 보정
sHTML = common.stringFilter.tagCorrector(sHTML);
return sHTML;
// custom attribute를 처리하지 못해 주석 처리 ex) data-user-style
// // '
abc
abc
'와 같이 짝기 맞지 않는 태그 보정
// var results = "";
// HTMLParser(sHTML, {
// start: function( tag, attrs, unary ) {
// results += "<" + tag;
//
// for ( var i = 0; i < attrs.length; i++ )
// results += " " + attrs[i].name + '="' + attrs[i].escaped + '"';
//
// results += (unary ? "/" : "") + ">";
// },
// end: function( tag ) {
// results += "";
// },
// chars: function( text ) {
// results += text;
// },
// comment: function( text ) {
// results += "";
// }
// });
// return results;
};
// ### cloneTagStruct
// > aEl로 받은 태그 구조를 복사해서 생성
// > ex) [P, SPAN, TEXT] ->
The errors were
! Failed to parse doc tags /blah/blah/dom.js: Cannot read property '1' of null
TypeError: Cannot read property '1' of null
at Object.module.exports.DOC_TAGS.return.parseValue (/home/elisa/repos/others/winternote/node_modules/groc/lib/doc_tags.coffee:180:23)
at Object.module.exports.Utils.parseDocTags (/home/elisa/repos/others/winternote/node_modules/groc/lib/utils.coffee:472:41)
at Default.module.exports.Base.renderFile (/home/elisa/repos/others/winternote/node_modules/groc/lib/styles/base.coffee:31:20)
at /home/elisa/repos/others/winternote/node_modules/groc/lib/project.coffee:74:24
at fs.js:266:14
at Object.oncomplete (fs.js:107:15)
The content of dom.js is shown below.
The text was updated successfully, but these errors were encountered: