Skip to content

Instantly share code, notes, and snippets.

@toodooleedoo
Last active September 25, 2017 16:02
Show Gist options
  • Select an option

  • Save toodooleedoo/fe0b2b83c4d5faf9ac92c82c224d506d to your computer and use it in GitHub Desktop.

Select an option

Save toodooleedoo/fe0b2b83c4d5faf9ac92c82c224d506d to your computer and use it in GitHub Desktop.

Boostrap and Simplenote Syncronization tool.

While wanting to switch from a Simplenote workflow and using nvALT to Boostrap I realized a manually import was going to be too complicated so i started a utility script.

Then i realized I could use this tool to continue parts of my note taking workflow in Simplenote including Cloud Syncronization, multiple device editing and there Android app which Boostrap still lacks.

Warning

This was a utility script so it is not yet very polished. It also does not keep tags from either app or modified time. I recommend understanding the script a bit and doing some tests. (See next)

Boostrap Duplicate cleanup utility script is also included.

This was created as i learned the hardway Boostrap maintains in memory reference to it's persistence and after migrations editing notes will cause duplicate entries.

I was unable to get a smart enough regex done after a good round of note cleanup so i leveraged a String Similiary library Which turned out to be REALLY cool and I imagine I will use this for other projects.

/*********************************************************
*
* @TITLE: Boostrap Duplicate Records
* @DESCRIPTION: Uses String Similiarity to compare note
* titles and contents to determine similiar records.
* Upon intelligently determining records which are safe
* to delete automatically if entries are close it will
* prompt you per entry if it is safe to delete.
*
* @INSTRUCTIONS: Change read and write directories and
* read the code. Do some test runs while commenting
* out the delete this was never fine tuned and meant
* as a utility script for me to run once.
*
* @AUTHOR: Eric Soukenka
* @DATE: April 20th 2017
*
* @NOTE: Created due to learning too late I had to restart
* Boostrap after manually editing .cson files if I was
* going to start using the application to modify entries.
*
* @NOTE: NOT YET POLISHED it was wrote during anger of
* learning I had hundreds of duplicates and regex'ing toe
* fix was too complicated.
*
********************************************************* */
var parseJson = require('parse-json');
var fs = require('fs');
var path = require('path');
var CSON = require('cson');
var crypto = require('crypto');
var stringSimilarity = require('string-similarity');
//var globals = require('globals');
var _ = require('underscore');
var query = require('cli-interact').getYesNo;
var readDir = '/Users/esouke/Boostnote/notes';
var writeDir = '/Users/esouke/Documents/Notes';
var separator = '\n=========================================================\n'
var cleanupFiles = [];
var maybeCleanupFiles = [];
files = fs.readdirSync(readDir);
filelist = [];
files.forEach(readfile => {
try {
if (path.extname(readfile) == '.cson') {
var txt = fs.readFileSync(readDir + '/' + readfile).toString();
var obj = CSON.parse(txt);
if (obj.title) {
files.forEach(readfile2 => {
var answer = false;
var txt2 = fs.readFileSync(readDir + '/' + readfile2).toString();
var obj2 = CSON.parse(txt + txt2)
if (obj2.title) {
x = stringSimilarity.compareTwoStrings(obj.title, obj2.title);
if (x > 0.6 && x != 1) {
y = stringSimilarity.compareTwoStrings(obj.content, obj2.content);
if (y > 0.9) {
console.log(`GOING: --------------- ${x} - ${y}`)
console.log(`OLD: ${obj.title}`);
console.log(`NEW: ${obj2.title}`);
console.log(`KEE: ${readDir}/${readfile}`)
console.log(`DEL: ${readDir}/${readfile2}`)
cleanupFiles.push(readDir + '/' + readfile2);
} else {
if (y > 0.5) {
console.log(`ASKING: ----------- ${x} - ${y}`)
console.log(`OLD: ${obj.title}`);
console.log(`NEW: ${obj2.title}`);
console.log(`KEE: ${readDir}/${readfile}`)
console.log(`DEL: ${readDir}/${readfile2}`)
maybeCleanupFiles.push(readDir + '/' + readfile2);
} else {
console.log(`SKIPPING: ${y} ${obj.title} - ${obj2.title} - ${x}`)
}
}
}
}
})
}
}
} catch (e) {
console.log(`ERROR: ${readfile}`);
}
})
for (index = 0; index < cleanupFiles.length; ++index) {
console.log(`Deleting: ${cleanupFiles[index]}`);
try {
fs.unlinkSync(cleanupFiles[index]);
} catch (e) {
console.log(`ERROR deleting: ${cleanupFiles[index]}`);
}
}
for (index = 0; index < maybeCleanupFiles.length; ++index) {
console.log("--------------------------------------");
try {
txt = fs.readFileSync(maybeCleanupFiles[index]).toString();
obj = CSON.parse(txt);
console.log(`Info: ${obj.title}`)
answer = query('delete');
if (answer) {
console.log(`Deleting: ${maybeCleanupFiles[index]}`);
try {
fs.unlinkSync(cleanupFiles[index]);
} catch (e) {
console.log(`ERROR deleting: ${cleanupFiles[index]}`);
}
} else {
console.log(`Skipping: ${maybeCleanupFiles[index]}`);
}
} catch (e) {
console.log('error');
}
}
/*********************************************************
*
* @TITLE: Simplenote and Boostrap Note Syncronization
*
* @DESCRIPTION: Supports two modes one which exports
* Boostrap notes and exports them to nvAlt .txt files.
* The other will export nvALT txt files to Boostrap .cson files
*
* @INSTRUCTIONS: Change readDir's and writeDir's at the top of
* both functions appropriately then run with no parameters for
* insrtructions.
*
* @AUTHOR: Eric Soukenka
* @DATE: April 20th 2017
*
* @NOTE: nvALT must have syncronization setting set to Plain
* Text files.
*
* @NOTE: Ensure you restart Boostrap after import to avoid
* duplicate entries.
*
* @NOTE: NOT YET POLISHED meaning it has a lot of my specific
* requirements and even the code is relatively embarrising :)
*
* !!! #################### !!!
* ####### IMPORTANT ##### !!!
* !!! Restart Boostrap after import!!!!!
*
********************************************************* */
var parseJson = require('parse-json');
var fs = require('fs');
var path = require('path');
var CSON = require('cson');
var crypto = require('crypto');
// TXT --> CSON
convertCsonToTxt = () => {
var skeleton = CSON.parseCSONFile('skeleton.cson');
var readDir = '/Users/esouke/Boostnote/notes';
var writeDir = '/Users/esouke/Documents/Notes';
var separator = '\n=========================================================\n'
fs.readdirSync(writeDir).forEach(function(file) {
if (path.extname(file) == '.txt') {
fs.unlink(writeDir + '/' + file)
}
})
files = fs.readdirSync(readDir);
filelist = [];
files.forEach(function(readfile) {
console.log(readfile)
if (path.extname(readfile) == '.cson') {
var txt = fs.readFileSync(readDir + '/' + readfile).toString();
var obj = CSON.parse(txt);
var writeFile = writeDir + '/' + obj.title + '.txt';
var writeBody = obj.content.replace(obj.title, '').replace(/\s+.*====/, '').replace(obj.title, '').replace(/^\s+|\s+$/g, '');
fs.writeFileSync(writeFile, obj.title + separator + writeBody);
}
})
console.log("IMPORTANT! Restart Boostrap if it is running!!!");
}
// CSON --> TXT
convertTxtToCson = () => {
var skeleton = CSON.parseCSONFile('skeleton.cson');
var readDir = '/Users/esouke/Documents/Notes';
var writeDir = '/Users/esouke/Boostnote/notes';
var separator = '\n=========================================================\n'
fs.readdirSync(writeDir).forEach(function(file) {
if (path.extname(file) == '.cson') {
fs.unlink(writeDir + '/' + file)
}
})
files = fs.readdirSync(readDir);
filelist = [];
files.forEach(function(readfile) {
if (path.extname(readfile) == '.txt') {
var txt = fs.readFileSync(readDir + '/' + readfile).toString();
var writeFile = writeDir + '/' + crypto.randomBytes(10).toString('hex') + '.cson';
readfile = readfile.replace(/\.[^/.]+$/, "");
skeleton.title = readfile;
var writeBody = txt.replace(readfile, '').replace(/\s+.*====/, '').replace(readfile, '').replace(/^\s+|\s+$/g, '')
skeleton.content = skeleton.title + separator + writeBody;
fs.writeFileSync(writeFile, CSON.stringify(skeleton));
skeleton.title = 'unknown';
skeleton.content = 'unknown';
}
});
}
var mode = process.argv[2];
if(mode == '-h' || mode == undefined) {
console.log('This will syncronize Boostrap and Simplenote');
console.log(`node ${process.argv[1]} simple-to-boost`);
console.log(`node ${process.argv[1]} boost-to-simple`);
} else if (mode == 'simple-to-boost') {
console.log('Syncing Simplenote to Boostrap');
convertTxtToCson();
} else if (mode == 'boost-to-simple') {
console.log('Syncing Boostrap to Simplenote');
convertCsonToTxt();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment