<commit_before>const fs = require('fs');
const path = require('path');
const chokidar = require('chokidar');

const _ = require('lodash');
const moment = require('moment');
const Datauri = require('datauri');

const arr = require('./utils/arr');
const uid = require('./utils/uid');

const electron = require('electron');


const BASE_LIB_PATH_KEY = 'libpath';


function setBaseLibraryPath(path) {
  return localStorage.setItem(BASE_LIB_PATH_KEY, path);
}


function getBaseLibraryPath() {
  return localStorage.getItem(BASE_LIB_PATH_KEY);
}

const DATA_REG = /\/(notes|folders|racks)\/([a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12})\.json$/;

function detectPath(path) {
  var m = DATA_REG.exec(path);
  if (!m) {
    return null
  }
  var dataType = m[1];
  var uid = m[2];
  return {
    dataType: dataType,
    uid: uid
  }
}

class Model {
  constructor(data) {
    this.uid = data.uid || uid.guid();
  }
  get data() { return { uid: this.uid } }

  update(data) {
    this.uid = data.uid;
  }

  static buildSaveDirPath() {
    return path.join(getBaseLibraryPath(), this.storagePrefix);
  }

  static buildSavePath(uid) {
    return path.join(this.buildSaveDirPath(), uid) + '.json';
  }

  static setModel(model) {
    if (!model) { return }
    var p = this.buildSavePath(model.uid);
    fs.mkdir(this.buildSaveDirPath(), (err) => {
      if (err) {}
      fs.writeFile(p, JSON.stringify(model.data));
    });
  }

  static removeModelFromStorage(model) {
    if (!model) { return }
    var p = this.buildSavePath(model.uid);
    fs.unlink(p);
  }

  static getModelsSync() {
    var dirPath = this.buildSaveDirPath();
    try {
      var files = fs.readdirSync(dirPath);
    } catch(e) {
      fs.mkdirSync(dirPath);
      files = [];
    }
    var valids = [];
    files.forEach((f) => {
      var p = path.join(dirPath, f);
      var d = detectPath(p);
      if (d && d.dataType == this.storagePrefix) {
        valids.push(new this(JSON.parse(fs.readFileSync(p))));
      }
    });
    return valids;
  }
}
Model.storagePrefix = 'models';


/**
 * [new Model(...)...].find(uidFinder("specify-your-uid")) => Model
 */
function uidFinder(uid){
  return (el) => {
    return el.uid == uid
  };
}


class Note extends Model {
  constructor(data) {
    super(data);

    this._body = data.body || '';
    this.folderUid = data.folderUid || null;
    this.doc = null;  // Codemirror.Doc object.
    this.qiitaURL = data.qiitaURL || null;

    if (data.updated_at) {
      this.updatedAt = moment(data.updated_at);
    } else {
      this.updatedAt = moment();
    }
    if (data.created_at) {
      this.createdAt = moment(data.created_at);
    } else {
      this.createdAt = moment();
    }
  }

  get data() {
    return _.assign(super.data, {
      body: this.body,
      folderUid: this.folderUid,
      updated_at: this.updatedAt,
      created_at: this.createdAt,
      qiitaURL: this.qiitaURL
    })
  }

  update(data) {
    super.update(data);
    this._body = data.body;
    this.folderUid = data.folderUid;
    this.updated_at = data.updated_at;
    this.created_at = data.created_at;
  }

  get body() {
    return this._body;
  }

  set body(newValue) {<commit_msg>move note bodies to separate .md file<commit_after>const fs = require('fs');
const path = require('path');
const chokidar = require('chokidar');

const _ = require('lodash');
const moment = require('moment');
const Datauri = require('datauri');

const arr = require('./utils/arr');
const uid = require('./utils/uid');

const BASE_LIB_PATH_KEY = 'libpath';

function setBaseLibraryPath(path) {
  return localStorage.setItem(BASE_LIB_PATH_KEY, path);
}

function getBaseLibraryPath() {
  return localStorage.getItem(BASE_LIB_PATH_KEY);
}

const DATA_REG = /\/(notes|folders|racks|meta)\/([a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12})\.json$/;

function detectPath(path) {
  var m = DATA_REG.exec(path);
  if (!m) {
    return null
  }
  var dataType = m[1];
  var uid = m[2];
  return {
    dataType: dataType == 'meta' ? 'notes' : dataType,
    uid: uid
  }
}

class Model {
  constructor(data) {
    this.uid = data.uid || uid.guid();
  }
  get data() { return { uid: this.uid } }

  update(data) {
    this.uid = data.uid;
  }

  static buildSaveDirPath() {
    if( this.storagePrefix == 'notes'){
      return path.join(getBaseLibraryPath(), 'meta');
    }
    return path.join(getBaseLibraryPath(), this.storagePrefix);
  }

  static buildSavePath(uid) {
    return path.join(this.buildSaveDirPath(), uid) + '.json';
  }

  static getMdFilePath(fileName) {
    return path.join(getBaseLibraryPath(), 'notes', fileName) + '.md';
  }

  static setModel(model) {
    if (!model) { return }
    var p = this.buildSavePath(model.uid);
    fs.mkdir(this.buildSaveDirPath(), (err) => {
      if (err) {}
      
      if(model.data.mdFilename && model.body){
        var md = this.getMdFilePath(model.data.mdFilename);
        fs.writeFile(md, model.body);
        if( model.currentMdFilename && model.currentMdFilename != model.data.mdFilename){
          fs.unlink( this.getMdFilePath(model.currentMdFilename) ); // Remove Old File if Name Changed
        }
      }
      fs.writeFile(p, JSON.stringify(model.data));
    });
  }

  static removeModelFromStorage(model) {
    if (!model) { return }
    var p = this.buildSavePath(model.uid);
    //@TODO remove md file
    fs.unlink(p);
  }

  static getModelsSync() {
    var dirPath = this.buildSaveDirPath();
    try {
      var files = fs.readdirSync(dirPath);
    } catch(e) {
      fs.mkdirSync(dirPath);
      files = [];
    }
    var valids = [];
    files.forEach((f) => {
      var p = path.join(dirPath, f);
      var d = detectPath(p);
      if (d && d.dataType == this.storagePrefix) {
        valids.push(new this(JSON.parse(fs.readFileSync(p))));
      }
    });
    return valids;
  }
}
Model.storagePrefix = 'models';


/**
 * [new Model(...)...].find(uidFinder("specify-your-uid")) => Model
 */
function uidFinder(uid){
  return (el) => {
    return el.uid == uid
  };
}


class Note extends Model {
  constructor(data) {
    super(data);

    this._body = data.body;
    this.currentMdFilename = data.mdFilename || '';
    this.loadBody(data);

    this.folderUid = data.folderUid || null;
    this.doc = null;  // Codemirror.Doc object.
    this.qiitaURL = data.qiitaURL || null;

    if (data.updated_at) {
      this.updatedAt = moment(data.updated_at);
    } else {
      this.updatedAt = moment();
    }
    if (data.created_at) {
      this.createdAt = moment(data.created_at);
    } else {
      this.createdAt = moment();
    }
  }

  get data() {
    return _.assign(super.data, {
      body: "",
      mdFilename: this.mdFilename,
      folderUid: this.folderUid,
      updated_at: this.updatedAt,
      created_at: this.createdAt,
      qiitaURL: this.qiitaURL
    })
  }

  get mdFilename() {
    return this.title ? this.title.replace(/[^\w _-]/g, '')+" ["+ this.uid +"]" : "["+ this.uid +"]";
  }

  update(data) {
    super.update(data);

    this._body = data.body;
    this.loadBody(data);

    this.folderUid = data.folderUid;
    this.updated_at = data.updated_at;
    this.created_at = data.created_at;
  }

  loadBody(data) {
    if(data.mdFilename){
      this._body = fs.readFileSync(Note.getMdFilePath(data.mdFilename)).toString();
    }
  }

  get body() {
    return this._body;
  }

  set body(newValue) {
{'fraction_non_alphanumeric': 0.16677893035160987, 'fraction_numerical': 0.004849791189546006, 'mean_word_length': 2.8268041237113404, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4692371', 'n_tokens_mistral': 2688, 'n_tokens_neox': 2626, 'n_words': 485}