utils.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. const fs = require('fs');
  2. // useful stuff
  3. const inherits = function(cls, superCtor, statics, prototype) {
  4. // eslint-disable-next-line no-underscore-dangle
  5. cls.super_ = superCtor;
  6. if (!prototype) {
  7. prototype = statics;
  8. statics = null;
  9. }
  10. if (statics) {
  11. Object.keys(statics).forEach(i => {
  12. Object.defineProperty(cls, i, Object.getOwnPropertyDescriptor(statics, i));
  13. });
  14. }
  15. const properties = {
  16. constructor: {
  17. value: cls,
  18. enumerable: false,
  19. writable: false,
  20. configurable: true,
  21. },
  22. };
  23. if (prototype) {
  24. Object.keys(prototype).forEach(i => {
  25. properties[i] = Object.getOwnPropertyDescriptor(prototype, i);
  26. });
  27. }
  28. cls.prototype = Object.create(superCtor.prototype, properties);
  29. };
  30. // eslint-disable-next-line no-control-regex
  31. const xmlDecodeRegex = /[<>&'"\x7F\x00-\x08\x0B-\x0C\x0E-\x1F]/;
  32. const utils = {
  33. nop() {},
  34. promiseImmediate(value) {
  35. return new Promise(resolve => {
  36. if (global.setImmediate) {
  37. setImmediate(() => {
  38. resolve(value);
  39. });
  40. } else {
  41. // poorman's setImmediate - must wait at least 1ms
  42. setTimeout(() => {
  43. resolve(value);
  44. }, 1);
  45. }
  46. });
  47. },
  48. inherits,
  49. dateToExcel(d, date1904) {
  50. return 25569 + ( d.getTime() / (24 * 3600 * 1000) ) - (date1904 ? 1462 : 0);
  51. },
  52. excelToDate(v, date1904) {
  53. const millisecondSinceEpoch = Math.round((v - 25569 + (date1904 ? 1462 : 0)) * 24 * 3600 * 1000);
  54. return new Date(millisecondSinceEpoch);
  55. },
  56. parsePath(filepath) {
  57. const last = filepath.lastIndexOf('/');
  58. return {
  59. path: filepath.substring(0, last),
  60. name: filepath.substring(last + 1),
  61. };
  62. },
  63. getRelsPath(filepath) {
  64. const path = utils.parsePath(filepath);
  65. return `${path.path}/_rels/${path.name}.rels`;
  66. },
  67. xmlEncode(text) {
  68. const regexResult = xmlDecodeRegex.exec(text);
  69. if (!regexResult) return text;
  70. let result = '';
  71. let escape = '';
  72. let lastIndex = 0;
  73. let i = regexResult.index;
  74. for (; i < text.length; i++) {
  75. const charCode = text.charCodeAt(i);
  76. switch (charCode) {
  77. case 34: // "
  78. escape = '&quot;';
  79. break;
  80. case 38: // &
  81. escape = '&amp;';
  82. break;
  83. case 39: // '
  84. escape = '&apos;';
  85. break;
  86. case 60: // <
  87. escape = '&lt;';
  88. break;
  89. case 62: // >
  90. escape = '&gt;';
  91. break;
  92. case 127:
  93. escape = '';
  94. break;
  95. default: {
  96. if (charCode <= 31 && (charCode <= 8 || (charCode >= 11 && charCode !== 13))) {
  97. escape = '';
  98. break;
  99. }
  100. continue;
  101. }
  102. }
  103. if (lastIndex !== i) result += text.substring(lastIndex, i);
  104. lastIndex = i + 1;
  105. if (escape) result += escape;
  106. }
  107. if (lastIndex !== i) return result + text.substring(lastIndex, i);
  108. return result;
  109. },
  110. xmlDecode(text) {
  111. return text.replace(/&([a-z]*);/g, c => {
  112. switch (c) {
  113. case '&lt;':
  114. return '<';
  115. case '&gt;':
  116. return '>';
  117. case '&amp;':
  118. return '&';
  119. case '&apos;':
  120. return '\'';
  121. case '&quot;':
  122. return '"';
  123. default:
  124. return c;
  125. }
  126. });
  127. },
  128. validInt(value) {
  129. const i = parseInt(value, 10);
  130. return !Number.isNaN(i) ? i : 0;
  131. },
  132. isDateFmt(fmt) {
  133. if (!fmt) {
  134. return false;
  135. }
  136. // must remove all chars inside quotes and []
  137. fmt = fmt.replace(/\[[^\]]*]/g, '');
  138. fmt = fmt.replace(/"[^"]*"/g, '');
  139. // then check for date formatting chars
  140. const result = fmt.match(/[ymdhMsb]+/) !== null;
  141. return result;
  142. },
  143. fs: {
  144. exists(path) {
  145. return new Promise(resolve => {
  146. fs.access(path, fs.constants.F_OK, err => {
  147. resolve(!err);
  148. });
  149. });
  150. },
  151. },
  152. toIsoDateString(dt) {
  153. return dt.toIsoString().subsstr(0, 10);
  154. },
  155. parseBoolean(value) {
  156. return value === true || value === 'true' || value === 1 || value === '1';
  157. },
  158. };
  159. module.exports = utils;