- "use strict";
- function isContainer(node) {
- switch (node._type) {
- case 'Document':
- case 'BlockQuote':
- case 'List':
- case 'Item':
- case 'Paragraph':
- case 'Header':
- case 'Emph':
- case 'Strong':
- case 'Link':
- case 'Image':
- return true;
- default:
- return false;
- }
- }
- var resumeAt = function(node, entering) {
- this.current = node;
- this.entering = (entering === true);
- };
- var next = function(){
- var cur = this.current;
- var entering = this.entering;
- if (cur === null) {
- return null;
- }
- var container = isContainer(cur);
- if (entering && container) {
- if (cur._firstChild) {
- this.current = cur._firstChild;
- this.entering = true;
- } else {
- // stay on node but exit
- this.entering = false;
- }
- } else if (cur._next === null) {
- this.current = cur._parent;
- this.entering = false;
- } else {
- this.current = cur._next;
- this.entering = true;
- }
- return {entering: entering, node: cur};
- };
- var NodeWalker = function(root) {
- return { current: root,
- root: root,
- entering: true,
- next: next,
- resumeAt: resumeAt };
- };
- var Node = function(nodeType, sourcepos) {
- this._type = nodeType;
- this._parent = null;
- this._firstChild = null;
- this._lastChild = null;
- this._prev = null;
- this._next = null;
- this._sourcepos = sourcepos;
- this._lastLineBlank = false;
- this._open = true;
- this._strings = null;
- this._string_content = null;
- this._literal = null;
- this._listData = null;
- this._info = null;
- this._destination = null;
- this._title = null;
- this._isFenced = false;
- this._fenceChar = null;
- this._fenceLength = 0;
- this._fenceOffset = null;
- this._level = null;
- };
- var proto = Node.prototype;
- Node.prototype.isContainer = function() {
- return isContainer(this);
- };
- Object.defineProperty(proto, 'type', {
- get: function() { return this._type; },
- });
- Object.defineProperty(proto, 'firstChild', {
- get: function() { return this._firstChild; },
- });
- Object.defineProperty(proto, 'lastChild', {
- get: function() { return this._lastChild; },
- });
- Object.defineProperty(proto, 'next', {
- get: function() { return this._next; },
- });
- Object.defineProperty(proto, 'prev', {
- get: function() { return this._prev; },
- });
- Object.defineProperty(proto, 'parent', {
- get: function() { return this._parent; },
- });
- Object.defineProperty(proto, 'sourcepos', {
- get: function() { return this._sourcepos; },
- });
- Object.defineProperty(proto, 'literal', {
- get: function() { return this._literal; },
- set: function(s) { this._literal = s; }
- });
- Object.defineProperty(proto, 'destination', {
- get: function() { return this._destination; },
- set: function(s) { this._destination = s; }
- });
- Object.defineProperty(proto, 'title', {
- get: function() { return this._title; },
- set: function(s) { this._title = s; }
- });
- Object.defineProperty(proto, 'info', {
- get: function() { return this._info; },
- set: function(s) { this._info = s; }
- });
- Object.defineProperty(proto, 'level', {
- get: function() { return this._level; },
- set: function(s) { this._level = s; }
- });
- Object.defineProperty(proto, 'listType', {
- get: function() { return this._listData.type; },
- set: function(t) { this._listData.type = t; }
- });
- Object.defineProperty(proto, 'listTight', {
- get: function() { return this._listData.tight; },
- set: function(t) { this._listData.tight = t; }
- });
- Object.defineProperty(proto, 'listStart', {
- get: function() { return this._listData.start; },
- set: function(n) { this._listData.start = n; }
- });
- Object.defineProperty(proto, 'listDelimiter', {
- get: function() { return this._listData.delimiter; },
- set: function(delim) { this._listData.delimiter = delim; }
- });
- Node.prototype.appendChild = function(child) {
- child.unlink();
- child._parent = this;
- if (this._lastChild) {
- this._lastChild._next = child;
- child._prev = this._lastChild;
- this._lastChild = child;
- } else {
- this._firstChild = child;
- this._lastChild = child;
- }
- };
- Node.prototype.prependChild = function(child) {
- child.unlink();
- child._parent = this;
- if (this._firstChild) {
- this._firstChild._prev = child;
- child._next = this._firstChild;
- this._firstChild = child;
- } else {
- this._firstChild = child;
- this._lastChild = child;
- }
- };
- Node.prototype.unlink = function() {
- if (this._prev) {
- this._prev._next = this._next;
- } else if (this._parent) {
- this._parent._firstChild = this._next;
- }
- if (this._next) {
- this._next._prev = this._prev;
- } else if (this._parent) {
- this._parent._lastChild = this._prev;
- }
- this._parent = null;
- this._next = null;
- this._prev = null;
- };
- Node.prototype.insertAfter = function(sibling) {
- sibling.unlink();
- sibling._next = this._next;
- if (sibling._next) {
- sibling._next._prev = sibling;
- }
- sibling._prev = this;
- this._next = sibling;
- sibling._parent = this._parent;
- if (!sibling._next) {
- sibling._parent._lastChild = sibling;
- }
- };
- Node.prototype.insertBefore = function(sibling) {
- sibling.unlink();
- sibling._prev = this._prev;
- if (sibling._prev) {
- sibling._prev._next = sibling;
- }
- sibling._next = this;
- this._prev = sibling;
- sibling._parent = this._parent;
- if (!sibling._prev) {
- sibling._parent._firstChild = sibling;
- }
- };
- Node.prototype.walker = function() {
- var walker = new NodeWalker(this);
- return walker;
- };
- module.exports = Node;
- /* Example of use of walker:
- var walker = w.walker();
- var event;
- while (event = walker.next()) {
- console.log(event.entering, event.node.type());
- }
- */
|