Home Reference Source

cables_dev/cables_electron/src/export/export_html_electron.js

  1. import fs from "fs";
  2. import { SharedExportService } from "cables-shared-api";
  3. import path from "path";
  4. import archiver from "archiver";
  5. import { fileURLToPath } from "url";
  6. import settings from "../electron/electron_settings.js";
  7. import electronApp from "../electron/main.js";
  8. import helper from "../utils/helper_util.js";
  9. import projectsUtil from "../utils/projects_util.js";
  10. export default class HtmlExportElectron extends SharedExportService
  11. {
  12. constructor(provider, _exportOptions, user)
  13. {
  14. super(provider, {}, user);
  15. this.archive = archiver;
  16. this.options.logLevel = "info";
  17. this.options.hideMadeWithCables = true;
  18. this.options.combineJs = false;
  19. this.options.minify = false;
  20. this.options.handleAssets = "all";
  21. this.options.rewriteAssetPorts = false;
  22. this.options.flattenAssetNames = true;
  23. this.finalAssetPath = "assets/";
  24. }
  25. static getName()
  26. {
  27. return "html";
  28. }
  29. static getExportOptions(user, teams, project, exportQuota)
  30. {
  31. return {
  32. "type": this.getName(),
  33. "allowed": true,
  34. "possible": true,
  35. "fields": {}
  36. };
  37. }
  38. doExport(project, cb)
  39. {
  40. this.collectFiles(
  41. project,
  42. this.createZip.bind(this),
  43. (collectErr, callbackError) =>
  44. {
  45. callbackError({ "msg": collectErr });
  46. },
  47. this.options,
  48. cb
  49. );
  50. }
  51. /* private */
  52. createZip(project, files, callbackFinished)
  53. {
  54. const zipFileName = this._projectsUtil.getExportFileName(project, this.getName());
  55. const zipPath = this._projectsUtil.getExportTargetPath(project);
  56. const finalZipFileName = path.join(zipPath, zipFileName);
  57. if (fs.existsSync(zipPath))
  58. {
  59. this._doZip(files, finalZipFileName, (result) =>
  60. {
  61. const fileUrl = helper.pathToFileURL(finalZipFileName);
  62. result.url = fileUrl;
  63. this.addLog("saved file to <a onclick=\"CABLES.CMD.ELECTRON.openFileManager('" + fileUrl + "');\">" + finalZipFileName + "</a>");
  64. callbackFinished(result);
  65. });
  66. }
  67. else
  68. {
  69. electronApp.exportProjectFileDialog(zipFileName).then((chosenFileName) =>
  70. {
  71. if (chosenFileName)
  72. {
  73. this._doZip(files, chosenFileName, (result) =>
  74. {
  75. const fileUrl = helper.pathToFileURL(finalZipFileName);
  76. result.url = fileUrl;
  77. this.addLog("saved file to <a onclick=\"CABLES.CMD.ELECTRON.openFileManager('" + fileUrl + "');\">" + finalZipFileName + "</a>");
  78. callbackFinished(result);
  79. });
  80. }
  81. else
  82. {
  83. const outputErr = "no export directory chosen";
  84. const result = { "error": outputErr };
  85. callbackFinished(result);
  86. }
  87. });
  88. }
  89. }
  90. collectFiles(project, callbackFilesCollected, callbackError, options, next)
  91. {
  92. this._log.info("...export");
  93. if (project)
  94. {
  95. options.handleAssets = options.handleAssets || "auto";
  96. this._exportProject(
  97. project,
  98. callbackFilesCollected,
  99. callbackError,
  100. options,
  101. next
  102. );
  103. }
  104. else
  105. {
  106. const err2 = "PROJECT_NOT_FOUND";
  107. callbackError(err2, (serviceResult) =>
  108. {
  109. next(serviceResult.msg, serviceResult);
  110. });
  111. }
  112. }
  113. _getFilesForProjects(theProjects, options, cb)
  114. {
  115. if (!theProjects)
  116. {
  117. cb([]);
  118. return;
  119. }
  120. const theFiles = [];
  121. const user = settings.getCurrentUser();
  122. theProjects.forEach((project) =>
  123. {
  124. let assetFilenames = this._projectsUtil.getUsedAssetFilenames(project, true);
  125. if (options.handleAssets === "all" && project._id)
  126. {
  127. const assetPath = path.join(this._projectsUtil.getAssetPath(project._id), "assets/");
  128. const assets = this._helperUtil.getFileNamesRecursive(assetPath);
  129. assets.forEach((asset) =>
  130. {
  131. if (!path.basename(asset).startsWith(".")) assetFilenames.push(path.join(assetPath, asset));
  132. });
  133. }
  134. assetFilenames = this._helperUtil.uniqueArray(assetFilenames);
  135. assetFilenames.forEach((fileName) =>
  136. {
  137. const fileDb = this._filesUtil.getFileDb(fileName, user, project);
  138. theFiles.push(fileDb);
  139. });
  140. });
  141. cb(theFiles);
  142. }
  143. _doAfterExport(originalProject, credentials, exportNumber, result)
  144. {
  145. const currentProjectFile = settings.getCurrentProjectFile();
  146. const currentProject = settings.getCurrentProject();
  147. if (currentProject) currentProject.exports = exportNumber;
  148. if (currentProjectFile) projectsUtil.writeProjectToFile(currentProjectFile, currentProject);
  149. return originalProject;
  150. }
  151. _getNameForZipEntry(fn, allFiles)
  152. {
  153. if (fn.substr(0, 1) === "/") fn = fn.substr(1);
  154. let fnNew = path.basename(fn);
  155. if (this.options.flattenAssetNames)
  156. {
  157. fnNew = fnNew.replaceAll("/", "_");
  158. }
  159. let assetDir = this.finalAssetPath;
  160. if (allFiles.includes(fnNew))
  161. {
  162. fnNew = path.join(this._helperUtil.generateUUID(), fnNew);
  163. }
  164. return path.join(assetDir, fnNew);
  165. }
  166. _getPortValueReplacement(filePathAndName, fn, lzipFileName)
  167. {
  168. return lzipFileName.replace(path.win32.sep, path.posix.sep);
  169. }
  170. _doAfterCombine(jsCode, options)
  171. {
  172. return jsCode;
  173. }
  174. _resolveFileName(filePathAndName, pathStr, project)
  175. {
  176. let result = filePathAndName || "";
  177. if (result.startsWith("/")) result = result.replace("/", "");
  178. if (result.startsWith("file:/")) result = fileURLToPath(filePathAndName);
  179. let finalPath = this.finalAssetPath;
  180. if (this.options.assetsInSubdirs && project && project._id) finalPath = path.join(this.finalAssetPath, project._id, "/");
  181. if (this.options.rewriteAssetPorts) result = result.replace(pathStr, finalPath);
  182. if (result.startsWith("assets/"))
  183. {
  184. return result.replace("assets/", "");
  185. }
  186. else
  187. {
  188. return result;
  189. }
  190. }
  191. _addAssets(proj, allFiles, options)
  192. {
  193. for (let iaf = 0; iaf < allFiles.length; iaf++)
  194. {
  195. if (!allFiles[iaf].path) continue;
  196. const assetPath = this._getAssetPath(allFiles[iaf]);
  197. let lzipFileName = allFiles[iaf].path.replace(this._projectsUtil.getAssetPath(proj._id), "");
  198. lzipFileName = this.appendFile(assetPath, lzipFileName, options.handleAssets);
  199. allFiles.push(lzipFileName);
  200. }
  201. return this._replaceAssetFilePathes(proj, options.handleAssets);
  202. }
  203. _getAssetPath(file)
  204. {
  205. return file.path;
  206. }
  207. }