Desktop markdown wiki app. Built with node, Electron Framework and AngularJS.

file-service.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. angular.module('codexApp')
  2. .service('FileService', [ '$rootScope', '$http', 'ThumbnailService', function($rootScope, $http, ThumbnailService) {
  3. var notes_dir = "/Users/james/dev/codex/codex";
  4. var default_notes_dir = "/Users/james/dev/codex/codex/inbox";
  5. var default_home_note = "/Users/james/dev/codex/codex/index.md"
  6. var notes = [];
  7. var current_note = "";
  8. var note_history = [];
  9. var note_history_index = 0;
  10. var prettySize = function(bytes) {
  11. if (bytes <= 1024) {
  12. return bytes + " KB"
  13. } else {
  14. var megabytes = parseFloat(Math.round(bytes/1024 * 100) / 100).toFixed(0);
  15. return megabytes + " MB"
  16. }
  17. }
  18. var getFilePathExtension = function(path) {
  19. var filename = path.split('\\').pop().split('/').pop();
  20. var lastIndex = filename.lastIndexOf(".");
  21. if (lastIndex < 1) return "";
  22. return filename.substr(lastIndex + 1);
  23. }
  24. var getFileType = function(path) {
  25. var extension = getFilePathExtension(path);
  26. switch (extension) {
  27. case "pdf":
  28. return "Document";
  29. case "jpg":
  30. return "Image";
  31. case "png":
  32. return "Image";
  33. case "md":
  34. return "Markdown";
  35. default:
  36. return "File";
  37. }
  38. }
  39. var directorySize = function(dir) {
  40. var filesystem = require("fs");
  41. var size = 0;
  42. var results = [];
  43. filesystem.readdirSync(dir).forEach(function(file) {
  44. file_path = dir+'/'+file;
  45. var stat = filesystem.statSync(file_path);
  46. if (stat && stat.isDirectory()) {
  47. results = results.concat(directorySize(file_path))
  48. } else {
  49. if(file != ".DS_Store") {
  50. size = size + stat["size"];
  51. //console.log("* " + stat["size"] + " KB -> " + file_path)
  52. }
  53. }
  54. });
  55. return size;
  56. }
  57. var noteCount = function(){
  58. var count = $scope.notes.length
  59. switch (count) {
  60. case 0:
  61. return '0 notes';
  62. case 1:
  63. return '1 note';
  64. default:
  65. return count + ' notes';
  66. }
  67. }
  68. var getThumbnail = function(file_path) {
  69. var type = getFileType(file_path);
  70. switch (type) {
  71. case "Markdown":
  72. return ThumbnailService.createNoteThumbnail(file_path);
  73. default:
  74. return "";
  75. }
  76. }
  77. var isValidFile = function(file) {
  78. if(file != ".DS_Store" && file != "info.json") {
  79. var parts = file.split('.');
  80. if (parts[parts.length -2] == "thumb") {
  81. return false;
  82. } else {
  83. return true
  84. }
  85. }
  86. }
  87. var SetFileInfo = function(jsonData, dir, file_path, stat) {
  88. //console.log(jsonData.title);
  89. if (typeof(jsonData)==='undefined') jsonData = {};
  90. if(jsonData.title != "" && jsonData.title != undefined){
  91. var title = jsonData.title;
  92. } else {
  93. var title = getNameFromPath(file_path);
  94. }
  95. if(jsonData.thumbnail != "" && jsonData.thumbnail != undefined){
  96. var thumbnail_path = jsonData.thumbnail;
  97. } else {
  98. var thumbnail_path = getThumbnail(file_path);
  99. }
  100. var file_obj = {
  101. title: title,
  102. path: file_path,
  103. size: prettySize(directorySize(dir)),
  104. type: getFileType(file_path),
  105. author: jsonData.author,
  106. index: jsonData.index,
  107. id: jsonData.id,
  108. created_at: dateFormat(stat["birthdate"], "mediumDate"),
  109. modified_at: dateFormat(stat["mtime"], "mediumDate"),
  110. accessed_at: dateFormat(stat["atime"], "mediumDate"),
  111. thumbnail: thumbnail_path
  112. }
  113. return file_obj;
  114. }
  115. var getNotesFromFolders = function(dir) {
  116. if (typeof(dir)==='undefined') dir = notes_dir;
  117. var filesystem = require("fs");
  118. filesystem.readdirSync(dir).forEach(function(file) {
  119. file_path = dir+'/'+file;
  120. var stat = filesystem.statSync(file_path);
  121. if (stat && stat.isDirectory()) {
  122. notes = notes.concat(getNotesFromFolders(file_path))
  123. } else {
  124. if(file == "info.json"){
  125. filesystem.readFile(file_path, function(err, data) {
  126. var jsonData = JSON.parse(data);
  127. var file_obj = SetFileInfo(jsonData, dir, file_path, stat)
  128. notes.push(file_obj);
  129. });
  130. }
  131. }
  132. });
  133. return notes;
  134. };
  135. this.getNotesFromFolders = getNotesFromFolders;
  136. var getAllFilesFromFolder = function(dir) {
  137. if (typeof(dir)==='undefined') dir = notes_dir;
  138. var filesystem = require("fs");
  139. var results = [];
  140. filesystem.readdirSync(dir).forEach(function(file) {
  141. file_path = dir+'/'+file;
  142. var stat = filesystem.statSync(file_path);
  143. if (stat && stat.isDirectory()) {
  144. results = results.concat(getAllFilesFromFolder(file_path))
  145. } else {
  146. if(isValidFile(file)) {
  147. var jsonData = {};
  148. var file_obj = SetFileInfo(jsonData, dir, file_path, stat)
  149. results.push(file_obj);
  150. }
  151. }
  152. //console.log(file_obj);
  153. });
  154. $rootScope.$broadcast('file-service:files-loaded');
  155. return results;
  156. };
  157. var findNoteInFolder = function(note_id, dir) {
  158. if (typeof(dir)==='undefined') dir = notes_dir;
  159. var filesystem = require("fs");
  160. var results = [];
  161. filesystem.readdirSync(dir).forEach(function(file) {
  162. file_path = dir+'/'+file;
  163. var stat = filesystem.statSync(file_path);
  164. if (stat && stat.isDirectory()) {
  165. results = results.concat(findNoteInFolder(note_id, file_path))
  166. } else {
  167. if(file == "info.json"){
  168. filesystem.readFile(file_path, function(err, data) {
  169. var jsonData = JSON.parse(data);
  170. console.log(jsonData.id)
  171. if(jsonData.id == note_id){
  172. var file_obj = SetFileInfo(jsonData, dir, file_path, stat)
  173. results.push(file_obj);
  174. }
  175. });
  176. }
  177. }
  178. });
  179. console.log(results);
  180. return results[0];
  181. };
  182. this.saveFile = function(file_path, content){
  183. var fs = require('fs');
  184. fs.writeFile(file_path, content, 'utf-8', function(err) {
  185. if(err) {
  186. return console.log(err);
  187. }
  188. console.log("-> FILE SAVED: " + file_path);
  189. });
  190. }
  191. var getNote = function(file_path){
  192. var filesystem = require("fs");
  193. var stat = filesystem.statSync(file_path);
  194. var file_obj = {
  195. title: "",
  196. path: file_path,
  197. size: stat['size'],
  198. type: getFileType(file_path),
  199. author: "",
  200. index: "",
  201. id: "",
  202. created_at: dateFormat(stat["birthdate"], "mediumDate"),
  203. modified_at: dateFormat(stat["mtime"], "mediumDate"),
  204. accessed_at: dateFormat(stat["atime"], "mediumDate")
  205. }
  206. return file_obj
  207. }
  208. var getNameFromPath = function(path) {
  209. path = path.split('/');
  210. var filename = path[path.length - 1];
  211. //filename = filename.split('.');
  212. //filename.pop();
  213. //name = filename[filename.length -1];
  214. return filename
  215. }
  216. var getUrlParts = function(url) {
  217. var a = document.createElement('a');
  218. a.href = url;
  219. return {
  220. href: a.href,
  221. host: a.host,
  222. hostname: a.hostname,
  223. port: a.port,
  224. pathname: a.pathname,
  225. protocol: a.protocol,
  226. hash: a.hash,
  227. search: a.search
  228. };
  229. }
  230. var absoluteToRelativeURL = function(current_url, absolute_url) {
  231. // split urls and create arrays
  232. var current_path = current_url.split('/');
  233. var absolute_path = getUrlParts(absolute_url).pathname.split('/');
  234. // remove the current note's filename from the url and the image filename from the url
  235. //current_path.pop();
  236. current_path.shift();
  237. //absolute_path.shift();
  238. // count how many folders the current path has
  239. var current_path_count = 0;
  240. for (var i = 0; i < current_path.length; i++) {
  241. current_path_count = current_path_count + 1;
  242. }
  243. // count how many folders the absolute path has
  244. var absolute_path_count = 0;
  245. for (var i = 0; i < absolute_path.length; i++) {
  246. absolute_path_count = absolute_path_count + 1;
  247. }
  248. absolute_path_count = absolute_path_count - 3;
  249. //dif = current_path_count - (absolute_path_count -1);
  250. for (var i = 0; i < absolute_path_count; i++) {
  251. absolute_path.shift();
  252. }
  253. // make the relative path a string again
  254. var relative_path = absolute_path.join('/');
  255. console.log("* Converted relative URL: " + relative_path)
  256. return relative_path;
  257. }
  258. // Absolute to relative URL
  259. this.absoluteToRelativeURL = function(current_url, absolute_url) {
  260. return absoluteToRelativeURL(current_url, absolute_url);
  261. }
  262. // Get folders
  263. var getFolders = function(root) {
  264. if (typeof(root)==='undefined') root = notes_dir;
  265. var filesystem = require("fs");
  266. var results = [];
  267. filesystem.readdirSync(root).forEach(function(file) {
  268. file_path = root+'/'+file;
  269. var stat = filesystem.statSync(file_path);
  270. if (stat && stat.isDirectory()) {
  271. results.push(SetFileInfo( undefined, root, file_path, stat));
  272. }
  273. });
  274. console.log(results);
  275. return results;
  276. }
  277. this.getFolders = function(root){
  278. return getFolders(root);
  279. }
  280. // Sort files
  281. var date_sort_asc = function (date1, date2) {
  282. if (date1.modified_at > date2.modified_at) return 1;
  283. if (date1.modified_at < date2.modified_at) return -1;
  284. return 0;
  285. };
  286. var date_sort_desc = function (date1, date2) {
  287. if (date1.modified_at > date2.modified_at) return -1;
  288. if (date1.modified_at < date2.modified_at) return 1;
  289. return 0;
  290. };
  291. var filterNotes = function(files) {
  292. var filtered = [];
  293. for (var i = 0; i < files.length; i++) {
  294. if(files[i].type == "Markdown") {
  295. filtered.push(files[i]);
  296. }
  297. }
  298. return filtered;
  299. }
  300. // RESPONSE
  301. this.getAllFiles = function() {
  302. notes = getAllFilesFromFolder();
  303. return notes.sort(date_sort_asc);
  304. }
  305. this.getAllNotes = function() {
  306. notes = getAllFilesFromFolder();
  307. notes = filterNotes(notes);
  308. return notes.sort(date_sort_asc);
  309. }
  310. this.getNote = function(path) {
  311. return getNote(path);
  312. }
  313. this.getCurrentNote = function() {
  314. return current_note;
  315. }
  316. this.setCurrentNote = function(note) {
  317. //console.log("searcing for: " + note_id)
  318. current_note = note;
  319. if((note_history.length -1) != note_history_index){
  320. var dif = note_history.length - note_history_index - 1;
  321. for (var i = 0; i < dif; i++) {
  322. note_history.pop();
  323. }
  324. }
  325. note_history.push(current_note);
  326. note_history_index = note_history.length -1;
  327. //console.log(current_note);
  328. //console.log("Current_note: " + current_note.title)
  329. }
  330. this.goToPreviousNote = function(){
  331. if(note_history_index > 0) {
  332. note_history_index = note_history_index - 1;
  333. current_note = note_history[note_history_index];
  334. }
  335. }
  336. this.goToNextNote = function(){
  337. if(note_history_index < (note_history.length - 1)){
  338. note_history_index = note_history_index + 1;
  339. current_note = note_history[note_history_index];
  340. }
  341. }
  342. this.getNotesDir = function() {
  343. return notes_dir;
  344. }
  345. this.getDefaultNotesDir = function() {
  346. return default_notes_dir;
  347. }
  348. this.getDefaultNote = function() {
  349. return getNote(default_home_note);
  350. }
  351. }])