message-accumulator
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -19,3 +19,3 @@ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if('value'in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor}}();/** | ||
* limitations under the License. | ||
*/var _ilibTreeNode=require('ilib-tree-node');var _ilibTreeNode2=_interopRequireDefault(_ilibTreeNode);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError('Cannot call a class as a function')}}/** | ||
*/var _ilibTreeNode=require('ilib-tree-node');var _ilibTreeNode2=_interopRequireDefault(_ilibTreeNode);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError('Cannot call a class as a function')}}function clone(obj){return obj?Object.assign({},obj):{}}/** | ||
* MessageAccumulator.js - accumulate a translatable message as a string | ||
@@ -38,6 +38,7 @@ */var MessageAccumulator=function(){/** | ||
* @private | ||
*/value:function _parse(string,mapping,parent){var match=void 0,re=/(<(c\d+)>.*<\/\2>)/g,first=/^<c(\d+)>/;var parts=string.split(re);for(var i=0;i<parts.length;i++){first.lastIndex=0;if((match=first.exec(parts[i]))!==null){var index=match[1];var len=match[0].length;// strip off the outer tags before processing the stuff in the middle | ||
*/value:function _parse(string,mapping,parent){var match=void 0,re=/(<(c\d+)>.*<\/\2>)/gs,first=/^<c(\d+)>/,selfclosing=/(<c(\d+)\/>)/g;var parts=string.split(re);for(var i=0;i<parts.length;i++){first.lastIndex=0;selfclosing.lastIndex=0;if((match=first.exec(parts[i]))!==null){var index=match[1];var len=match[0].length;// strip off the outer tags before processing the stuff in the middle | ||
var substr=parts[i].substring(len,parts[i].length-len-1);var component=new _ilibTreeNode2.default({type:'component',parent:parent,index:index,extra:mapping&&mapping['c'+index]});this._parse(substr,mapping,component);parent.add(component);i++;// skip the number in the next iteration | ||
}else if(parts[i]&&parts[i].length){// don't store empty strings | ||
parent.add(new _ilibTreeNode2.default({type:'text',value:parts[i]}))}}}/** | ||
}else if(parts[i]&&parts[i].length){var subparts=parts[i].split(selfclosing);for(var j=0;j<subparts.length;j++){selfclosing.lastIndex=0;if((match=selfclosing.exec(subparts[j]))!==null){var _index=match[2];parent.add(new _ilibTreeNode2.default({type:'component',parent:parent,index:_index,extra:mapping&&mapping['c'+_index]}));j++;// skip the number in the next iteration | ||
}else if(subparts[j]&&subparts[j].length){// don't store empty strings | ||
parent.add(new _ilibTreeNode2.default({type:'text',value:subparts[j]}))}}}}}/** | ||
* Add text to the current context of the string. | ||
@@ -61,2 +62,19 @@ * @param {string} text the text to add | ||
return}var extra=this.currentLevel.extra;this.currentLevel=this.currentLevel.parent;return extra}/** | ||
* @private | ||
*/},{key:'_getString',value:function _getString(rootnode){if(rootnode.children.length===0){return rootnode.value||''}return rootnode.children.map(function(child){return child.toArray().map(function(node){if(node.type==='component'){if(node.index>-1){if(node.use==='start'){return'<c'+node.index+'>'}else if(node.use==='end'){return'</c'+node.index+'>'}else{// self-closing | ||
return'<c'+node.index+'/>'}}}else{return node.value}}).join('')}).join('')}/** | ||
* @private | ||
*/},{key:'_isEmpty',value:function _isEmpty(node){var _this=this;if(node.type==='text'&&node.value.trim()!=='')return false;if(node.type==='component'&&node.children&&node.children.length){return node.children.every(function(child){return _this._isEmpty(child)})}return true}/** | ||
* @private | ||
*/},{key:'_renumber',value:function _renumber(node){var _this2=this;if(node.type==='component'){node.index=this.componentIndex++;this.mapping['c'+node.index]=node.extra}if(node.children){node.children.forEach(function(child){_this2._renumber(child)})}}/** | ||
* @private | ||
*/},{key:'_minimize',value:function _minimize(){if(this.minimized)return;var value,changed=true;if(!this.prefixes)this.prefixes=[];if(!this.suffixes)this.suffixes=[];function valueMap(node){if(node.type==='component'){var value=clone(node.extra);value.use=node.use;return value}return node.value}// keep stripping off parts until we haven't changed anything, or we have stripped off everything | ||
while(changed&&this.root.children&&this.root.children.length){changed=false;var subroot=this.root;// check for "outer" components -- components that surround localizable text without adding anything to it | ||
while(subroot.children&&subroot.children.length===1&&subroot.children[0].type!=='text'){subroot=subroot.children[0];value=clone(subroot.extra);value.use='start';this.prefixes.push(value);value=clone(subroot.extra);value.use='end';this.suffixes=[value].concat(this.suffixes);changed=true}var children=subroot.children;// find empty components at the start | ||
var i=0;while(i<children.length&&children[i]&&this._isEmpty(children[i])){this.prefixes=this.prefixes.concat(children[i].toArray().map(valueMap));i++;changed=true}children=i>0?children.slice(i):children;// then find empty components at the end | ||
var i=children.length-1;while(i>0&&children[i]&&this._isEmpty(children[i])){this.suffixes=children[i].toArray().map(valueMap).concat(this.suffixes);i--;changed=true}// now strip off the leading and trailing whitespace | ||
if(children.length&&children[0].type==='text'){var re=/^\s+/;var match=re.exec(children[0].value);if(match){children[0].value=children[0].value.substring(match[0].length);this.prefixes.push(match[0]);changed=true}}var last=children.length-1;if(children.length&&children[last].type==='text'){var re=/\s+$/;var match=re.exec(children[last].value);if(match){children[last].value=children[last].value.substring(0,children[last].value.length-match[0].length);this.suffixes=[match[0]].concat(this.suffixes);changed=true}}this.root.children=i<children.length-1?children.slice(0,i+1):children;// then do it all again until nothing changes! | ||
}// now walk the tree again and renumber any components so that we don't start at some number greater | ||
// than zero | ||
this.componentIndex=0;this.mapping={};this._renumber(this.root);this.minimized=true}/** | ||
* Return the message accumulated so far, including any components | ||
@@ -67,4 +85,46 @@ * as a string that contains "c" + a number to represent those | ||
* @return {string} the accumulated string so far | ||
*/},{key:'getString',value:function getString(){return this.root.toArray().map(function(node){if(node.type==='component'){if(node.use==='start'&&node.index>-1){return'<c'+node.index+'>'}else if(node.use==='end'&&node.index>-1){return'</c'+node.index+'>'}else{// self-closing | ||
return'<c'+node.index+'></c'+node.index+'>'}}else{return node.value}}).join('')}/** | ||
*/},{key:'getString',value:function getString(){return this._getString(this.root)}/** | ||
* Return all of the irrelevant parts of the string at the beginning | ||
* of the message.<p> | ||
* | ||
* For a minimal string, all of the components that are irrelevant | ||
* for translation are removed. This method returns all of the irrelevant | ||
* components and text units that appear at the beginning of the string. | ||
* | ||
* @returns {Array.<Object>} an array of "extra" and text units that | ||
* are irrelevant | ||
*/},{key:'getPrefix',value:function getPrefix(){this._minimize();return this.prefixes||[]}/** | ||
* Return the message accumulated so far as a string, including | ||
* any components, and leaving out any contexts that are irrelevant | ||
* for translation purposes. This method is similar to getString() | ||
* with the irrelevant parts removed. This includes: | ||
* | ||
* <ul> | ||
* <li>Any components that surround the entire message | ||
* <li>Any components that are at the beginning or end of the message | ||
* and which do not have any translatable text in them. | ||
* <li>Any text at the beginning or end of the string that only | ||
* contains whitespace. | ||
* </ul> | ||
* | ||
* A minimal string must either start with non-whitespace text or end with | ||
* non-whitespace text or both.<p> | ||
* | ||
* After all the irrelevant parts are removed, the remaining components | ||
* are renumbered so that the first one to appear starts at zero, the | ||
* second one is one, etc. | ||
* | ||
* @return {string} the accumuilated string so far with all irrelevant | ||
* components removed. | ||
*/},{key:'getMinimalString',value:function getMinimalString(){this._minimize();return this._getString(this.root)}/** | ||
* Return all of the irrelevant parts of the string at the end | ||
* of the message.<p> | ||
* | ||
* For a minimal string, all of the components that are irrelevant | ||
* for translation are removed. This method returns all of the irrelevant | ||
* components and text units that appear at the end of the string. | ||
* | ||
* @returns {Array.<Object>} an array of "extra" and text units that | ||
* are irrelevant | ||
*/},{key:'getSuffix',value:function getSuffix(){this._minimize();return this.suffixes||[]}/** | ||
* Return the number of characters of non-whitespace text that | ||
@@ -71,0 +131,0 @@ * have been accumulated so far in this accumulator. Components |
@@ -23,2 +23,6 @@ /** | ||
function clone(obj) { | ||
return obj ? Object.assign({}, obj) : {}; | ||
} | ||
/** | ||
@@ -69,9 +73,11 @@ * MessageAccumulator.js - accumulate a translatable message as a string | ||
let match, | ||
re = /(<(c\d+)>.*<\/\2>)/g, | ||
first = /^<c(\d+)>/; | ||
re = /(<(c\d+)>.*<\/\2>)/gs, | ||
first = /^<c(\d+)>/, | ||
selfclosing = /(<c(\d+)\/>)/g; | ||
const parts = string.split(re); | ||
let parts = string.split(re); | ||
for (var i = 0; i < parts.length; i++) { | ||
first.lastIndex = 0; | ||
selfclosing.lastIndex = 0; | ||
if ((match = first.exec(parts[i])) !== null) { | ||
@@ -93,7 +99,22 @@ const index = match[1]; | ||
} else if (parts[i] && parts[i].length) { | ||
// don't store empty strings | ||
parent.add(new Node({ | ||
type: 'text', | ||
value: parts[i] | ||
})); | ||
let subparts = parts[i].split(selfclosing); | ||
for (var j = 0; j < subparts.length; j++) { | ||
selfclosing.lastIndex = 0; | ||
if ((match = selfclosing.exec(subparts[j])) !== null) { | ||
const index = match[2]; | ||
parent.add(new Node({ | ||
type: 'component', | ||
parent, | ||
index, | ||
extra: mapping && mapping[`c${index}`] | ||
})); | ||
j++; // skip the number in the next iteration | ||
} else if (subparts[j] && subparts[j].length) { | ||
// don't store empty strings | ||
parent.add(new Node({ | ||
type: 'text', | ||
value: subparts[j] | ||
})); | ||
} | ||
} | ||
} | ||
@@ -156,2 +177,148 @@ } | ||
/** | ||
* @private | ||
*/ | ||
_getString(rootnode) { | ||
if (rootnode.children.length === 0) { | ||
return rootnode.value || ""; | ||
} | ||
return rootnode.children.map(child => { | ||
return child.toArray().map(node => { | ||
if (node.type === "component") { | ||
if (node.index > -1) { | ||
if (node.use === "start") { | ||
return `<c${node.index}>`; | ||
} else if (node.use === "end") { | ||
return `</c${node.index}>`; | ||
} else { | ||
// self-closing | ||
return `<c${node.index}/>`; | ||
} | ||
} | ||
} else { | ||
return node.value; | ||
} | ||
}).join(''); | ||
}).join(''); | ||
} | ||
/** | ||
* @private | ||
*/ | ||
_isEmpty(node) { | ||
if (node.type === "text" && node.value.trim() !== "") return false; | ||
if (node.type === "component" && node.children && node.children.length) { | ||
return node.children.every(child => { | ||
return this._isEmpty(child); | ||
}); | ||
} | ||
return true; | ||
} | ||
/** | ||
* @private | ||
*/ | ||
_renumber(node) { | ||
if (node.type === "component") { | ||
node.index = this.componentIndex++; | ||
this.mapping[`c${node.index}`] = node.extra; | ||
} | ||
if (node.children) { | ||
node.children.forEach(child => { | ||
this._renumber(child); | ||
}); | ||
} | ||
} | ||
/** | ||
* @private | ||
*/ | ||
_minimize() { | ||
if (this.minimized) return; | ||
var value, changed = true; | ||
if (!this.prefixes) this.prefixes = []; | ||
if (!this.suffixes) this.suffixes = []; | ||
function valueMap(node) { | ||
if (node.type === "component") { | ||
var value = clone(node.extra); | ||
value.use = node.use; | ||
return value; | ||
} | ||
return node.value; | ||
} | ||
// keep stripping off parts until we haven't changed anything, or we have stripped off everything | ||
while (changed && this.root.children && this.root.children.length) { | ||
changed = false; | ||
var subroot = this.root; | ||
// check for "outer" components -- components that surround localizable text without adding anything to it | ||
while (subroot.children && subroot.children.length === 1 && subroot.children[0].type !== "text") { | ||
subroot = subroot.children[0]; | ||
value = clone(subroot.extra); | ||
value.use = "start"; | ||
this.prefixes.push(value); | ||
value = clone(subroot.extra); | ||
value.use = "end"; | ||
this.suffixes = [value].concat(this.suffixes); | ||
changed = true; | ||
} | ||
var children = subroot.children; | ||
// find empty components at the start | ||
var i = 0; | ||
while (i < children.length && children[i] && this._isEmpty(children[i])) { | ||
this.prefixes = this.prefixes.concat(children[i].toArray().map(valueMap)); | ||
i++; | ||
changed = true; | ||
} | ||
children = i > 0 ? children.slice(i) : children; | ||
// then find empty components at the end | ||
var i = children.length - 1; | ||
while (i > 0 && children[i] && this._isEmpty(children[i])) { | ||
this.suffixes = children[i].toArray().map(valueMap).concat(this.suffixes); | ||
i--; | ||
changed = true; | ||
} | ||
// now strip off the leading and trailing whitespace | ||
if (children.length && children[0].type === "text") { | ||
var re = /^\s+/; | ||
var match = re.exec(children[0].value); | ||
if (match) { | ||
children[0].value = children[0].value.substring(match[0].length); | ||
this.prefixes.push(match[0]); | ||
changed = true; | ||
} | ||
} | ||
var last = children.length-1; | ||
if (children.length && children[last].type === "text") { | ||
var re = /\s+$/; | ||
var match = re.exec(children[last].value); | ||
if (match) { | ||
children[last].value = children[last].value.substring(0, children[last].value.length - match[0].length); | ||
this.suffixes = [match[0]].concat(this.suffixes); | ||
changed = true; | ||
} | ||
} | ||
this.root.children = i < children.length - 1 ? children.slice(0, i+1) : children; | ||
// then do it all again until nothing changes! | ||
} | ||
// now walk the tree again and renumber any components so that we don't start at some number greater | ||
// than zero | ||
this.componentIndex = 0; | ||
this.mapping = {}; | ||
this._renumber(this.root); | ||
this.minimized = true; | ||
} | ||
/** | ||
* Return the message accumulated so far, including any components | ||
@@ -164,19 +331,67 @@ * as a string that contains "c" + a number to represent those | ||
getString() { | ||
return this.root.toArray().map(node => { | ||
if (node.type === "component") { | ||
if (node.use === "start" && node.index > -1) { | ||
return `<c${node.index}>`; | ||
} else if (node.use === "end" && node.index > -1) { | ||
return `</c${node.index}>`; | ||
} else { | ||
// self-closing | ||
return `<c${node.index}></c${node.index}>`; | ||
} | ||
} else { | ||
return node.value; | ||
} | ||
}).join(''); | ||
return this._getString(this.root); | ||
} | ||
/** | ||
* Return all of the irrelevant parts of the string at the beginning | ||
* of the message.<p> | ||
* | ||
* For a minimal string, all of the components that are irrelevant | ||
* for translation are removed. This method returns all of the irrelevant | ||
* components and text units that appear at the beginning of the string. | ||
* | ||
* @returns {Array.<Object>} an array of "extra" and text units that | ||
* are irrelevant | ||
*/ | ||
getPrefix() { | ||
this._minimize(); | ||
return this.prefixes || []; | ||
} | ||
/** | ||
* Return the message accumulated so far as a string, including | ||
* any components, and leaving out any contexts that are irrelevant | ||
* for translation purposes. This method is similar to getString() | ||
* with the irrelevant parts removed. This includes: | ||
* | ||
* <ul> | ||
* <li>Any components that surround the entire message | ||
* <li>Any components that are at the beginning or end of the message | ||
* and which do not have any translatable text in them. | ||
* <li>Any text at the beginning or end of the string that only | ||
* contains whitespace. | ||
* </ul> | ||
* | ||
* A minimal string must either start with non-whitespace text or end with | ||
* non-whitespace text or both.<p> | ||
* | ||
* After all the irrelevant parts are removed, the remaining components | ||
* are renumbered so that the first one to appear starts at zero, the | ||
* second one is one, etc. | ||
* | ||
* @return {string} the accumuilated string so far with all irrelevant | ||
* components removed. | ||
*/ | ||
getMinimalString() { | ||
this._minimize(); | ||
return this._getString(this.root); | ||
} | ||
/** | ||
* Return all of the irrelevant parts of the string at the end | ||
* of the message.<p> | ||
* | ||
* For a minimal string, all of the components that are irrelevant | ||
* for translation are removed. This method returns all of the irrelevant | ||
* components and text units that appear at the end of the string. | ||
* | ||
* @returns {Array.<Object>} an array of "extra" and text units that | ||
* are irrelevant | ||
*/ | ||
getSuffix() { | ||
this._minimize(); | ||
return this.suffixes || []; | ||
} | ||
/** | ||
* Return the number of characters of non-whitespace text that | ||
@@ -183,0 +398,0 @@ * have been accumulated so far in this accumulator. Components |
{ | ||
"name": "message-accumulator", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"main": "./message-accumulator-es5.js", | ||
@@ -54,7 +54,5 @@ "main-es6": "./message-accumulator.js", | ||
"dependencies": { | ||
"ilib-tree-node": "^1.0.0" | ||
"ilib-tree-node": "^1.1.0" | ||
}, | ||
"devDependencies": { | ||
"acorn": "^6.0.2", | ||
"acorn-jsx": "^5.0.0", | ||
"babel-core": "^6.26.0", | ||
@@ -65,2 +63,3 @@ "babel-preset-env": "*", | ||
"grunt": "^1.0.3", | ||
"grunt-babel": "^7.0.0", | ||
"grunt-contrib-clean": "^2.0.0", | ||
@@ -70,7 +69,6 @@ "grunt-contrib-jshint": "^2.0.0", | ||
"grunt-contrib-uglify": "^4.0.0", | ||
"grunt-babel": "^7.0.0", | ||
"load-grunt-tasks": "^4.0.0", | ||
"promise": "8.0.1", | ||
"nodeunit": "0.11.0" | ||
"nodeunit": "0.11.0", | ||
"promise": "8.0.1" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
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
75299
13
582
Updatedilib-tree-node@^1.1.0