Comparing version 0.1.1-alpha.1 to 0.1.1-alpha.2
{ | ||
"name": "l5x-js", | ||
"version": "0.1.1-alpha.1", | ||
"version": "0.1.1-alpha.2", | ||
"description": "A tool to help with parsing and generating Allen Bradley L5X files.", | ||
@@ -5,0 +5,0 @@ "main": "./src/index.js", |
const fs = require("fs"); | ||
const clone = require("clone"); | ||
const { resolve } = require("path"); | ||
@@ -7,2 +6,13 @@ const { hash } = require("../utilities"); | ||
// const ElementTypes = [ | ||
// "Controller", | ||
// "DataType", | ||
// "Tag", | ||
// "Member", | ||
// "Program", | ||
// "Routine", | ||
// "Rung", | ||
// "RLLContent" | ||
// ]; | ||
class Document { | ||
@@ -44,4 +54,2 @@ constructor(filepath = null, document_tree = null) { | ||
} | ||
this._mutable_dom = clone(this._dom); | ||
} | ||
@@ -56,6 +64,71 @@ | ||
get dom() { | ||
return this._mutable_dom; | ||
return this._dom; | ||
} | ||
/** | ||
* Finds the first desired element within the Document | ||
* | ||
* @param {string} type - Type of element to look for (e.g. Controller, Datatype, etc) | ||
* @param {object} [attr=null] - Object of attributes to match in element | ||
* @param {object} [search_tree=null] - Tree to search on | ||
* @returns {object|null} found documents | ||
* @memberof Document | ||
*/ | ||
findOne(type, attr = null, search_tree = null) { | ||
// Validate Inputs | ||
if (typeof type !== "string") | ||
throw new Error( | ||
`Find expected a type name of type <String> instead got type <${typeof type}>` | ||
); | ||
if (attr && typeof attr !== "object") | ||
throw new Error( | ||
`Find expected a attr of type <Object> or null instead got <${typeof attr}>` | ||
); | ||
if (search_tree && typeof search_tree !== "object") | ||
throw new Error( | ||
`Find expected a search tree of type <Object> or null instead got <${typeof search_tree}>` | ||
); | ||
// If no tree is passed then search from document root | ||
let tree = search_tree ? search_tree : this._dom; | ||
// Nothing left to search, return null | ||
if (!tree.elements || !Array.isArray(tree.elements) || tree.length === 0) return null; | ||
// Search elements | ||
for (let elem of tree.elements) { | ||
// Check if this is the desired element | ||
if (elem.name === type) { | ||
// Check if attributes match | ||
if (attr) { | ||
let attrMatch = true; | ||
for (let key of Object.keys(attr)) { | ||
if (!elem.attributes[key] || elem.attributes[key] !== attr[key]) | ||
attrMatch = false; | ||
} | ||
// Attributes match so return subtree | ||
if (attrMatch) return elem; | ||
} else { | ||
// No attributes need to match | ||
return elem; | ||
} | ||
} | ||
// Search branches for desired element | ||
const found = this.findOne(type, attr, elem); | ||
if (found) { | ||
if (Document.isDocument(found)) return found; | ||
else return new Document(null, found); | ||
} | ||
} | ||
// Nothing found, return null | ||
return null; | ||
} | ||
/** | ||
* Finds desired element within the Document | ||
@@ -66,3 +139,3 @@ * | ||
* @param {object} [search_tree=null] - Tree to search on | ||
* @returns {object|null} found subtree | ||
* @returns {Array|null} found documents | ||
* @memberof Document | ||
@@ -113,7 +186,7 @@ */ | ||
if (attrMatch) { | ||
returnArray.push(new Document(null, clone(elem))); | ||
returnArray.push(new Document(null, elem)); | ||
} | ||
} else { | ||
// No attributes need to match | ||
returnArray.push(new Document(null, clone(elem))); | ||
returnArray.push(new Document(null, elem)); | ||
} | ||
@@ -135,50 +208,107 @@ } else { | ||
/** | ||
* Attempts to replace existing document branch with passed document | ||
* -> returns true if successful | ||
* Appends element to doc._dom.elements | ||
* | ||
* @param {Document} doc | ||
* @returns {boolean} | ||
* @returns {Document} - this (for chaining) | ||
* @memberof Document | ||
*/ | ||
replace(doc) { | ||
append(doc) { | ||
if (!Document.isDocument(doc)) | ||
throw new Error( | ||
`Replace expected to receive doc of type <Document> instead got type <${typeof doc}>` | ||
`Append expected to receive doc of type <Document> instead got type <${typeof doc}>` | ||
); | ||
const _replace = tree => { | ||
// Nothing left to search, return null | ||
if (!tree.elements || !Array.isArray(tree.elements) || tree.elements.length === 0) | ||
return false; | ||
if (this._dom.elements && Array.isArray(this._dom.elements)) | ||
this._dom.elements.push(doc.dom); | ||
else this._dom.elements = [doc.dom]; | ||
// Search elements | ||
for (let i in tree.elements) { | ||
const elem = tree.elements[i]; | ||
// Check if this is the desired element | ||
if (elem.name === doc._dom.name) { | ||
// Check if attributes match | ||
if (doc._dom.attributes) { | ||
let attrMatch = true; | ||
for (let key of Object.keys(doc._dom.attributes)) { | ||
if ( | ||
!elem.attributes[key] || | ||
elem.attributes[key] !== doc._dom.attributes[key] | ||
) | ||
attrMatch = false; | ||
} | ||
return this; | ||
} | ||
// Attributes match so return subtree | ||
if (attrMatch) { | ||
tree.elements[i] = doc.dom; | ||
return true; | ||
} | ||
} | ||
} else { | ||
if (_replace(elem)) return true; | ||
} | ||
} | ||
return false; | ||
}; | ||
/** | ||
* Adds a tag to passed document | ||
* | ||
* @param {string} tagname | ||
* @param {object} [options={}] | ||
* @param {string} [prog=null] | ||
* @param {string} [description=null] | ||
* @memberof Document | ||
*/ | ||
addTag(tagname, options = {}, prog = null, description = null) { | ||
if (typeof tagname !== "string") | ||
throw new Error( | ||
`addTag expected tagname of type <String> instead got <${typeof tagname}>` | ||
); | ||
return _replace(this._dom); | ||
if (options && typeof options !== "object") | ||
throw new Error( | ||
`addTag expected options of type <Object> instead got <${typeof options}>` | ||
); | ||
if (prog && typeof prog !== "string") | ||
throw new Error(`addTag expected prog of type <String> instead got <${typeof prog}>`); | ||
if (description && typeof description !== "string") | ||
throw new Error( | ||
`addTag expected description of type <String> instead got <${typeof description}>` | ||
); | ||
// Merge defaults with passed options object | ||
const attributes = Object.assign( | ||
{}, | ||
{ TagType: "Base", DataType: "DINT", Class: "Standard", ExternalAccess: "Read/Write" }, | ||
options | ||
); | ||
/* eslint-disable indent */ | ||
// Find target to mount new tag too | ||
const target = prog | ||
? this.findOne("Program", { | ||
Name: prog | ||
}) | ||
: this.findOne("Controller"); | ||
if (!target) | ||
throw new Error( | ||
`addTag could not find a ${ | ||
prog ? "Program" : "Controller" | ||
} target element to mount tag` | ||
); | ||
// Build new tag element | ||
const tag = new Document(null, { | ||
type: "element", | ||
name: "Tag", | ||
attributes: { | ||
...attributes, | ||
Name: tagname | ||
}, | ||
elements: description | ||
? [ | ||
{ | ||
type: "element", | ||
name: "Description", | ||
elements: [ | ||
{ | ||
type: "cdata", | ||
cdata: description | ||
} | ||
] | ||
} | ||
] | ||
: [] | ||
}); | ||
// Get tags element from target | ||
let tags = target.findOne("Tags"); | ||
if (tags) tags.append(tag); | ||
else | ||
target.append( | ||
new Document(null, { | ||
type: "element", | ||
name: "Tags" | ||
}).append(tag) | ||
); | ||
/* eslint-enable indent */ | ||
} | ||
@@ -185,0 +315,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19696
359