helpers.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. // Copyright (c) 2018 Nikolai Suslov
  2. // Krestianstvo.org MIT license (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
  3. // VWF Apache License (https://github.com/NikolaySuslov/livecodingspace/blob/master/VWF_LICENSE.md)
  4. class Helpers {
  5. constructor() {
  6. console.log("helpers constructor");
  7. // List of valid ID characters for use in an instance.
  8. this.ValidIDChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  9. // List of valid extensions for VWF components.
  10. this.template_extensions = ["", ".yaml", ".json"];
  11. this.applicationRoot = "/"; //app
  12. }
  13. async Process(updatedURL) {
  14. var result =
  15. { 'public_path': "/", 'application': undefined, 'instance': undefined, 'private_path': undefined };
  16. var segments = this.GenerateSegments(updatedURL);
  17. var extension = undefined;
  18. while ((segments.length > 0) && (await this.IsExist(this.JoinPath(result['public_path'], segments[0])))) {
  19. result['public_path'] = this.JoinPath(result['public_path'], segments.shift());
  20. }
  21. if ((segments.length > 0) && (extension = await this.GetExtension(this.JoinPath(result['public_path'], segments[0])))) {
  22. result['application'] = segments.shift();
  23. } else if (extension = await this.GetExtension(this.JoinPath(result['public_path'], "index.vwf"))) {
  24. result['application'] = "index.vwf";
  25. }
  26. if (extension) {
  27. if ((segments.length > 0) && (this.IsInstanceID(segments[0]))) {
  28. result['instance'] = segments.shift();
  29. }
  30. if (segments.length > 0) {
  31. result['private_path'] = segments.join("/");
  32. }
  33. }
  34. return result;
  35. }
  36. // IsInstanceID tests if the passed in potential Instance ID
  37. // is a valid instance id.
  38. IsInstanceID(potentialInstanceID) {
  39. if (potentialInstanceID.match(/^[0-9A-Za-z]{16}$/)) {
  40. return true;
  41. }
  42. return false;
  43. }
  44. // GenerateInstanceID function creates a randomly generated instance ID.
  45. GenerateInstanceID() {
  46. var text = "";
  47. for (var i = 0; i < 16; i++)
  48. text += this.ValidIDChars.charAt(Math.floor(Math.random() * this.ValidIDChars.length));
  49. return text;
  50. }
  51. // JoinPath
  52. // Takes multiple arguments, joins them together into one path.
  53. JoinPath( /* arguments */) {
  54. var result = "";
  55. if (arguments.length > 0) {
  56. if (arguments[0]) {
  57. result = arguments[0];
  58. }
  59. for (var index = 1; index < arguments.length; index++) {
  60. var newSegment = arguments[index];
  61. if (newSegment == undefined) {
  62. newSegment = "";
  63. }
  64. if ((newSegment[0] == "/") && (result[result.length - 1] == "/")) {
  65. result = result + newSegment.slice(1);
  66. } else if ((newSegment[0] == "/") || (result[result.length - 1] == "/")) {
  67. result = result + newSegment;
  68. } else {
  69. result = result + "/" + newSegment;
  70. }
  71. //result = libpath.join( result, newSegment );
  72. }
  73. }
  74. return result;
  75. }
  76. async IsFileExist(path) {
  77. var seperatorFixedPath = path.slice(1);//path.replace(/\//g, '/');
  78. let worldName = seperatorFixedPath.split('/')[0];
  79. let fileName = seperatorFixedPath.replace(worldName + '/', "");
  80. let doc = await _LCS_WORLD_USER.get('worlds').get(worldName).get(fileName).once().then();
  81. if (doc) {
  82. return true
  83. }
  84. return false
  85. }
  86. async IsExist(path) {
  87. var seperatorFixedPath = path.slice(1);//path.replace(/\//g, '/');
  88. let doc = await _LCS_WORLD_USER.get('worlds').get(seperatorFixedPath).once().then();
  89. if (doc) {
  90. return true
  91. }
  92. return false
  93. }
  94. // GenerateSegments takes a string, breaks it into
  95. // '/' separated segments, and removes potential
  96. // blank first and last segments.
  97. GenerateSegments(argument) {
  98. var result = argument.split("/");
  99. if (result.length > 0) {
  100. if (result[0] == "") {
  101. result.shift();
  102. }
  103. }
  104. if (result.length > 0) {
  105. if (result[result.length - 1] == "") {
  106. result.pop();
  107. }
  108. }
  109. return result;
  110. }
  111. async GetExtension(path) {
  112. if (path.match(/\.vwf$/)) {
  113. for (const res of this.template_extensions) {
  114. let check = await this.IsFileExist(this.JoinPath(path + res).split(".").join("_"));
  115. if (check) return res
  116. }
  117. }
  118. return undefined;
  119. }
  120. get appPath() {
  121. return JSON.parse(localStorage.getItem('lcs_app')).path.public_path.slice(1)
  122. }
  123. get worldStateName() {
  124. let appConfig = JSON.parse(localStorage.getItem('lcs_app'));
  125. var saveName = appConfig.path.public_path.slice(1);
  126. let privatePath = appConfig.path.private_path;
  127. if (privatePath) {
  128. if (privatePath.indexOf('load') !== -1) {
  129. saveName = privatePath.split('/')[1];
  130. }
  131. }
  132. return saveName
  133. }
  134. getRoot(noUser) {
  135. var app = window.location.pathname;
  136. var pathSplit = app.split('/');
  137. if (pathSplit[0] == "") {
  138. pathSplit.shift();
  139. }
  140. if (pathSplit[pathSplit.length - 1] == "") {
  141. pathSplit.pop();
  142. }
  143. var inst = undefined;
  144. var instIndex = pathSplit.length - 1;
  145. if (pathSplit.length > 2) {
  146. if (pathSplit[pathSplit.length - 2] == "load") {
  147. instIndex = pathSplit.length - 3;
  148. }
  149. }
  150. if (pathSplit.length > 3) {
  151. if (pathSplit[pathSplit.length - 3] == "load") {
  152. instIndex = pathSplit.length - 4;
  153. }
  154. }
  155. inst = pathSplit[instIndex];
  156. var root = "";
  157. for (var i = 0; i < instIndex; i++) {
  158. if (root != "") {
  159. root = root + "/";
  160. }
  161. root = root + pathSplit[i];
  162. }
  163. if (root.indexOf('.vwf') != -1) root = root.substring(0, root.lastIndexOf('/'));
  164. if (noUser) {
  165. return {
  166. "root": root.replace(pathSplit[0] + '/', ""),
  167. "inst": inst
  168. }
  169. } else {
  170. return {
  171. "root": root,
  172. "inst": inst
  173. }
  174. }
  175. }
  176. get worldUser() {
  177. return this.getRoot(false).root.split('/')[0];
  178. }
  179. randId() {
  180. return '_' + Math.random().toString(36).substr(2, 9);
  181. }
  182. getRandomInt(min, max) {
  183. min = Math.ceil(min);
  184. max = Math.floor(max);
  185. return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
  186. }
  187. GUID() {
  188. var S4 = function () {
  189. return Math.floor(
  190. Math.random() * 0x10000 /* 65536 */
  191. ).toString(16);
  192. };
  193. return (
  194. S4() + S4() + "-" +
  195. S4() + "-" +
  196. S4() + "-" +
  197. S4() + "-" +
  198. S4() + S4() + S4()
  199. );
  200. }
  201. async sha256(message) {
  202. // encode as UTF-8
  203. const msgBuffer = new TextEncoder('utf-8').encode(message);
  204. // hash the message
  205. const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
  206. // convert ArrayBuffer to Array
  207. const hashArray = Array.from(new Uint8Array(hashBuffer));
  208. // convert bytes to hex string
  209. const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
  210. return hashHex;
  211. }
  212. replaceSubStringALL(target, search, replacement) {
  213. return target.split(search).join(replacement);
  214. };
  215. async getHtmlText(url) {
  216. let file = await fetch(url, { method: 'get' });
  217. let text = await file.text();
  218. return text
  219. }
  220. removeProps(obj) {
  221. Object.keys(obj).forEach(key =>
  222. (key === 'id' || key === 'patches' || key === 'random' || key === 'sequence') && delete obj[key] ||
  223. (obj[key] && typeof obj[key] === 'object') && this.removeProps(obj[key])
  224. );
  225. return obj;
  226. };
  227. getNodeDef(nodeID) {
  228. let node = vwf.getNode(nodeID, true);
  229. let nodeDefPure = this.removeProps(node);
  230. let nodeDef = this.removeGrammarObj(nodeDefPure);
  231. return nodeDef
  232. }
  233. removeGrammarObj(obj) {
  234. Object.keys(obj).forEach(key =>
  235. (key === 'grammar' || key === 'semantics') && delete obj[key] ||
  236. (obj[key] && typeof obj[key] === 'object') && this.removeGrammarObj(obj[key])
  237. );
  238. return obj;
  239. };
  240. httpGet(url) {
  241. return new Promise(function (resolve, reject) {
  242. // do the usual Http request
  243. let request = new XMLHttpRequest();
  244. request.open('GET', url);
  245. request.onload = function () {
  246. if (request.status == 200) {
  247. resolve(request.response);
  248. } else {
  249. reject(Error(request.statusText));
  250. }
  251. };
  252. request.onerror = function () {
  253. reject(Error('Network Error'));
  254. };
  255. request.send();
  256. });
  257. }
  258. async httpGetJson(url) {
  259. // check if the URL looks like a JSON file and call httpGet.
  260. let regex = /\.(json)$/i;
  261. if (regex.test(url)) {
  262. // call the async function, wait for the result
  263. return await this.httpGet(url);
  264. } else {
  265. throw Error('Bad Url Format');
  266. }
  267. }
  268. }
  269. export { Helpers }