Sow String

A Javascript library to transform indented strings into leafy trees.

Example GitHub License

How To Use?

Install

The package is on NPM:

npm install sowstring

Usage

For NodeJS, just require the file:

var SowString = require ("sowstring").SowString;

var tree = SowString (sourceString, optionsObject);

On browsers, include the script:

<script src="path/to/library/dist/sowstring.js"></script>
You will have SowString registered globally in the window object. The function has the classes SowString.Node and SowString.Leaf as well.

Options

Options should be passed as an object to the second argument of SowString (source, { options:here }) function, and all its fields are optionals:

emptyLines (Boolean) — when true, preserve the empty lines in the final tree items. When false, empty lines will be entirely ignored. Default: false.

error (Function) — when provided, it executes always when the indent is invalid in the string or made invalid by the intercept function. The function is called without arguments, with an handler object as this and ignores returns. It is the last chance to fix manually an indent error, and whether it is not fixed, it will fix automatically or throw an exception, according to fixIndent option. See below for a complete reference of the this object passed to the function, and its uses. Default: null.

fixIndent (Boolean) — when true, indent errors will be fixed automatically, if not error handler, nor intercept callback take care of it. If false, an exception is thrown, identifying the error and line of occurence. Default: false.

intercept (Function) — when provided, it executes the function for each line. The function is called without arguments, with an handler object as this and ignores returns. See below for a complete reference of the this object and its uses. The function will not handle empty lines. Default: null.

tabReplace (String or Number) — set this option to the string that will replace every TAB character (ASCII: 9), or to the amount of spaces that replace it. Default: string with 4 whitespaces.

useHeading (Boolean) — when true, tree omits each item before arrays of nodes and set those line as heading attributes of nodes. The option itself is saved in the tree outter node as useHeading to remember the tree scheme. Default: false.

Intercept and Error context object (this)

The callbacks error and intercept passed to the options are called without arguments. The handling is made through the this object. The object has some useful informations and functions to handle various cases. See below a list of properties and functions:

hasErrors (Boolean) — inform if the current indent is invalid according to the tree. See the section about invalid indent below.

indent (Number) — get or set the indent of the item. The indent is given by the number of whitespaces before the line start. Its concept is the same as the code indentation. Strings indented with 2 spaces will also have the indents multiple of 2 (0, 2, 4, 6…).

level (Number) — get or set the level assigned to the item. The level is the height of the item in the tree, according to the indent, being no indent the level 0, the first indent the level 1 and so on…

lineNum (Number, readonly) — number of the line currently being parsed in the given string.

startIndent (Number, readonly) — inform the original indent of the item when the function was called. This value will not update during the function execution.

startLevel (Number, readonly) — inform the original level of the item when the function was called. This value will not update during the function execution.

text (String) — get or set the text assigned to the item. The initial value is the line of the string assigned with the item.

discard () (no return) — the item and line will be completely ignored and will not be included in the resulting tree. Use this function to remove lines on the fly.

getProp (name) (returns the value) — get a custom property previously assigned to the current item.

setProp (name, value) (no return) — set a custom property to the current item. This is useful to assign the item with custom fields related to the user logic. There are some reserved names which you cannot use: constructor, prototype, indent, level, lineNum, parent and children.

setChild () (no return) — causes the item to be a child of the previous appended item. The item will have the same indent as the previous plus 1.

setParent () (no return) — causes the item to back to the parent level of the previous appended item. The item will have the same indent as the parent of the previous item.

setSibling () (no return) — causes the item to be a sibling of the previous appended item. The item will have the very same indent as the previous item.

setSiblingOfNext () (no return) — the item will not be appended in the tree while the next item is not appended. When the next item is appended, all the stack of "siblings of next" are appended before it, in the same level. It is the same process used to fix invalid indentations.

Tree to String

If you want to get back the tree as a string, you can use the toString method in the most outter (root) node. This node is the tree itself, which is returned from the SowString function.

var myString = myTree.toString ()

Here we also have options, which is also a plain object:

var myString = myTree.toString({…options…})

Options

details (Boolean) — If true, the resulting string will include a note between brackets [ ] defining if the object is a Node or Leaf, and the line that generated the item. Default: false.

Invalid indent and poisonous trees

If the string has inconsistent indentation, it msut be treated before the item is added on the tree. If no process fix the error, and fixIndent is false, an error of type Error will be thrown informing the line of occurence. Otherwise, the fixed indent is assigned to the item.

For example, consider the following tree:

Parent
Node 1
Node 2
Node 3
Node 4

Observe the Node 3 item, it has one space less than the previous item, but has three spaces more than the parent. It can be hard to realize what were the intention of the user. For the computer, the item cannot be the parent, as it has much more indentation, and cannot be a sibling because it is very little indented. So, it is not a parent, sibling or child, and there's no other state in our tree.

Solution I

This issue can be solved automatically by the library passing the option fixIndent as true. In this case, the item awaits for the next inclusion and is appended as sibling of next item.

Solution II

The user can set an error callback in the options. So, if the line as any issue relative to its indent, the function is called and the user can set a valid indent using the this object. If this function just call this.setSiblingOfNext ();, this code will do exactly the same as the fixIndent option.

If the error is not really solved in this option, the algorithm will fallback to the fixIndent option. If the option is not enabled, an error is thrown.

This approach can be combined with solution I and executes before that.

Solution III

The user can also check for indent errors in the intercept function passed in the options. The check can be made using the hasErrors field of the this object. If the indent has errors, the user can fix it manually.

The intercept function is executed before the error function, and both execute before the automatic fix (fixIndent). Then, the first try of the library is to use the intercept function, if there is an error in the indent, the error function is called and, if the error wasn't solved, the automatic fix is executed or an error is thrown.

This approach can be combined with solution I and II and executes before them.