Block.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. "use strict";
  2. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3. 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); } }
  4. function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  5. // Generated by CoffeeScript 2.5.1
  6. var Block, SpecialString, cloneAndMergeDeep, terminalWidth;
  7. SpecialString = require('./SpecialString');
  8. terminalWidth = require('../tools').getCols();
  9. var _require = require('../tools');
  10. cloneAndMergeDeep = _require.cloneAndMergeDeep;
  11. module.exports = Block = function () {
  12. var self;
  13. var Block = /*#__PURE__*/function () {
  14. function Block(_layout, _parent) {
  15. var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  16. var _name = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
  17. _classCallCheck(this, Block);
  18. this._layout = _layout;
  19. this._parent = _parent;
  20. this._name = _name;
  21. this._config = cloneAndMergeDeep(self.defaultConfig, config);
  22. this._closed = false;
  23. this._wasOpenOnce = false;
  24. this._active = false;
  25. this._buffer = '';
  26. this._didSeparateBlock = false;
  27. this._linePrependor = new this._config.linePrependor.fn(this._config.linePrependor.options);
  28. this._lineAppendor = new this._config.lineAppendor.fn(this._config.lineAppendor.options);
  29. this._blockPrependor = new this._config.blockPrependor.fn(this._config.blockPrependor.options);
  30. this._blockAppendor = new this._config.blockAppendor.fn(this._config.blockAppendor.options);
  31. }
  32. _createClass(Block, [{
  33. key: "_activate",
  34. value: function _activate() {
  35. var deactivateParent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
  36. if (this._active) {
  37. throw Error("This block is already active. This is probably a bug in RenderKid itself");
  38. }
  39. if (this._closed) {
  40. throw Error("This block is closed and cannot be activated. This is probably a bug in RenderKid itself");
  41. }
  42. this._active = true;
  43. this._layout._activeBlock = this;
  44. if (deactivateParent) {
  45. if (this._parent != null) {
  46. this._parent._deactivate(false);
  47. }
  48. }
  49. return this;
  50. }
  51. }, {
  52. key: "_deactivate",
  53. value: function _deactivate() {
  54. var activateParent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
  55. this._ensureActive();
  56. this._flushBuffer();
  57. if (activateParent) {
  58. if (this._parent != null) {
  59. this._parent._activate(false);
  60. }
  61. }
  62. this._active = false;
  63. return this;
  64. }
  65. }, {
  66. key: "_ensureActive",
  67. value: function _ensureActive() {
  68. if (!this._wasOpenOnce) {
  69. throw Error("This block has never been open before. This is probably a bug in RenderKid itself.");
  70. }
  71. if (!this._active) {
  72. throw Error("This block is not active. This is probably a bug in RenderKid itself.");
  73. }
  74. if (this._closed) {
  75. throw Error("This block is already closed. This is probably a bug in RenderKid itself.");
  76. }
  77. }
  78. }, {
  79. key: "_open",
  80. value: function _open() {
  81. if (this._wasOpenOnce) {
  82. throw Error("Block._open() has been called twice. This is probably a RenderKid bug.");
  83. }
  84. this._wasOpenOnce = true;
  85. if (this._parent != null) {
  86. this._parent.write(this._whatToPrependToBlock());
  87. }
  88. this._activate();
  89. return this;
  90. }
  91. }, {
  92. key: "close",
  93. value: function close() {
  94. this._deactivate();
  95. this._closed = true;
  96. if (this._parent != null) {
  97. this._parent.write(this._whatToAppendToBlock());
  98. }
  99. return this;
  100. }
  101. }, {
  102. key: "isOpen",
  103. value: function isOpen() {
  104. return this._wasOpenOnce && !this._closed;
  105. }
  106. }, {
  107. key: "write",
  108. value: function write(str) {
  109. this._ensureActive();
  110. if (str === '') {
  111. return;
  112. }
  113. str = String(str);
  114. this._buffer += str;
  115. return this;
  116. }
  117. }, {
  118. key: "openBlock",
  119. value: function openBlock(config, name) {
  120. var block;
  121. this._ensureActive();
  122. block = new Block(this._layout, this, config, name);
  123. block._open();
  124. return block;
  125. }
  126. }, {
  127. key: "_flushBuffer",
  128. value: function _flushBuffer() {
  129. var str;
  130. if (this._buffer === '') {
  131. return;
  132. }
  133. str = this._buffer;
  134. this._buffer = '';
  135. this._writeInline(str);
  136. }
  137. }, {
  138. key: "_toPrependToLine",
  139. value: function _toPrependToLine() {
  140. var fromParent;
  141. fromParent = '';
  142. if (this._parent != null) {
  143. fromParent = this._parent._toPrependToLine();
  144. }
  145. return this._linePrependor.render(fromParent);
  146. }
  147. }, {
  148. key: "_toAppendToLine",
  149. value: function _toAppendToLine() {
  150. var fromParent;
  151. fromParent = '';
  152. if (this._parent != null) {
  153. fromParent = this._parent._toAppendToLine();
  154. }
  155. return this._lineAppendor.render(fromParent);
  156. }
  157. }, {
  158. key: "_whatToPrependToBlock",
  159. value: function _whatToPrependToBlock() {
  160. return this._blockPrependor.render();
  161. }
  162. }, {
  163. key: "_whatToAppendToBlock",
  164. value: function _whatToAppendToBlock() {
  165. return this._blockAppendor.render();
  166. }
  167. }, {
  168. key: "_writeInline",
  169. value: function _writeInline(str) {
  170. var i, j, k, l, lineBreaksToAppend, m, ref, ref1, ref2, remaining; // special characters (such as <bg-white>) don't require
  171. // any wrapping...
  172. if (new SpecialString(str).isOnlySpecialChars()) {
  173. // ... and directly get appended to the layout.
  174. this._layout._append(str);
  175. return;
  176. } // we'll be removing from the original string till it's empty
  177. remaining = str; // we might need to add a few line breaks at the end of the text.
  178. lineBreaksToAppend = 0; // if text starts with line breaks...
  179. if (m = remaining.match(/^\n+/)) {
  180. // ... we want to write the exact same number of line breaks
  181. // to the layout.
  182. for (i = j = 1, ref = m[0].length; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) {
  183. this._writeLine('');
  184. }
  185. remaining = remaining.substr(m[0].length, remaining.length);
  186. } // and if the text ends with line breaks...
  187. if (m = remaining.match(/\n+$/)) {
  188. // we want to write the exact same number of line breaks
  189. // to the end of the layout.
  190. lineBreaksToAppend = m[0].length;
  191. remaining = remaining.substr(0, remaining.length - m[0].length);
  192. } // now let's parse the body of the text:
  193. while (remaining.length > 0) {
  194. // anything other than a break line...
  195. if (m = remaining.match(/^[^\n]+/)) {
  196. // ... should be wrapped as a block of text.
  197. this._writeLine(m[0]);
  198. remaining = remaining.substr(m[0].length, remaining.length); // for any number of line breaks we find inside the text...
  199. } else if (m = remaining.match(/^\n+/)) {
  200. // ... we write one less break line to the layout.
  201. for (i = k = 1, ref1 = m[0].length; 1 <= ref1 ? k < ref1 : k > ref1; i = 1 <= ref1 ? ++k : --k) {
  202. this._writeLine('');
  203. }
  204. remaining = remaining.substr(m[0].length, remaining.length);
  205. }
  206. } // if we had line breaks to append to the layout...
  207. if (lineBreaksToAppend > 0) {
  208. // ... we append the exact same number of line breaks to the layout.
  209. for (i = l = 1, ref2 = lineBreaksToAppend; 1 <= ref2 ? l <= ref2 : l >= ref2; i = 1 <= ref2 ? ++l : --l) {
  210. this._writeLine('');
  211. }
  212. }
  213. } // wraps a line into multiple lines if necessary, adds horizontal margins,
  214. // etc, and appends it to the layout.
  215. }, {
  216. key: "_writeLine",
  217. value: function _writeLine(str) {
  218. var line, lineContent, lineContentLength, remaining, roomLeft, toAppend, toAppendLength, toPrepend, toPrependLength; // we'll be cutting from our string as we go
  219. remaining = new SpecialString(str);
  220. while (true) {
  221. // left margin...
  222. // this will continue until nothing is left of our block.
  223. toPrepend = this._toPrependToLine(); // ... and its length
  224. toPrependLength = new SpecialString(toPrepend).length; // right margin...
  225. toAppend = this._toAppendToLine(); // ... and its length
  226. toAppendLength = new SpecialString(toAppend).length; // how much room is left for content
  227. roomLeft = this._layout._config.terminalWidth - (toPrependLength + toAppendLength); // how much room each line of content will have
  228. lineContentLength = Math.min(this._config.width, roomLeft); // cut line content, only for the amount needed
  229. lineContent = remaining.cut(0, lineContentLength, true); // line will consist of both margins and the content
  230. line = toPrepend + lineContent.str + toAppend; // send it off to layout
  231. this._layout._appendLine(line);
  232. if (remaining.isEmpty()) {
  233. break;
  234. }
  235. }
  236. }
  237. }]);
  238. return Block;
  239. }();
  240. ;
  241. self = Block;
  242. Block.defaultConfig = {
  243. blockPrependor: {
  244. fn: require('./block/blockPrependor/Default'),
  245. options: {
  246. amount: 0
  247. }
  248. },
  249. blockAppendor: {
  250. fn: require('./block/blockAppendor/Default'),
  251. options: {
  252. amount: 0
  253. }
  254. },
  255. linePrependor: {
  256. fn: require('./block/linePrependor/Default'),
  257. options: {
  258. amount: 0
  259. }
  260. },
  261. lineAppendor: {
  262. fn: require('./block/lineAppendor/Default'),
  263. options: {
  264. amount: 0
  265. }
  266. },
  267. lineWrapper: {
  268. fn: require('./block/lineWrapper/Default'),
  269. options: {
  270. lineWidth: null
  271. }
  272. },
  273. width: terminalWidth,
  274. prefixRaw: '',
  275. suffixRaw: ''
  276. };
  277. return Block;
  278. }.call(void 0);