title | tags | created | modified | attachments | ||
---|---|---|---|---|---|---|
A title |
|
2019-02-17T19:54:53.942Z |
2019-02-19T16:27:42.872Z |
|
Last active
February 28, 2019 05:00
-
-
Save AnonymerNiklasistanonym/7b32fa0a9f19f50f401cdf3685f54289 to your computer and use it in GitHub Desktop.
Convert a markdown note written in Notable (https://github.com/notable/notable) to a markdown document readable by another Markdown editor like Typora (https://typora.io/) via a CLI node script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs') | |
const path = require('path') | |
const colors = require('colors') | |
/** | |
* Info option, when true enable performance tracking and other infos | |
*/ | |
let enableInfo = false | |
/** | |
* String that replaces `@attachment` in `img` tags | |
*/ | |
let replaceWith = 'attachments' | |
/** | |
* CLI Help output | |
*/ | |
const helpOutput = () => { | |
console.log('Description:\n' + | |
'\tScraps Markdown note created with Notable for used resources to\n' + | |
'\tedit it and export it to a new file that can be edited in Typora.') | |
console.log('Example:\n\t$ node ' + | |
colors.yellow('.\\notableNoteToTypora.js ') + | |
colors.green('filePath.md ') + | |
colors.red('-enableOptionalOption') + | |
'\n\tFile was written: "filePath_typora.md"') | |
console.log('Options:\n' + '\t-info\t\t\t\t' + | |
colors.grey('Get information about performance\n\t\t\t\t\tand other things') + | |
'\n\t-customReplace ' + colors.magenta('"attachmentsDir"') + '\t' + | |
colors.grey('Replace "@attachment" in img tags\n\t\t\t\t\twith a custom string')) | |
} | |
/** | |
* CLI Version output | |
*/ | |
const versionOutput = () => { | |
console.log('0.0.2') | |
} | |
// Check if a file was given | |
if (process.argv.length < 3) { | |
console.error('No file path specified!\n') | |
helpOutput() | |
process.exit(1) | |
} | |
// Check if options are correct | |
if (process.argv.length >= 3) { | |
let infoAlreadyEnabled = false | |
let replaceAlreadyEnabled = false | |
let ignoreNext = false | |
for (let i = 3; i < process.argv.length; i++) { | |
if (process.argv[i] === '-info') { | |
if (infoAlreadyEnabled) { | |
console.error(`'-info' option cannot bet enabled twice!\n`) | |
helpOutput() | |
process.exit(1) | |
} else { | |
infoAlreadyEnabled = true | |
enableInfo = true | |
} | |
} else if (process.argv[i] === '-customReplace') { | |
if (replaceAlreadyEnabled) { | |
console.error(`'-customReplace' option cannot bet enabled twice!\n`) | |
helpOutput() | |
process.exit(1) | |
} else { | |
replaceAlreadyEnabled = true | |
if (i + 1 > process.argv.length) { | |
console.error(`'-customReplace' option needs a following argument!\n`) | |
helpOutput() | |
process.exit(1) | |
} | |
ignoreNext = true | |
replaceWith = process.argv[i + 1] | |
} | |
} else { | |
if (!ignoreNext) { | |
console.error(`Unknown option: "${colors.red(process.argv[i])}"\n`) | |
helpOutput() | |
process.exit(1) | |
} else { | |
ignoreNext = false | |
} | |
} | |
} | |
} | |
// Check if instead of a file help/version is wanted | |
if (process.argv[2] === '--help' || | |
process.argv[2] === '-help' || | |
process.argv[2] === 'help') { | |
helpOutput() | |
process.exit(0) | |
} else if (process.argv[2] === '--version' || | |
process.argv[2] === '-version' || | |
process.argv[2] === 'version') { | |
versionOutput() | |
process.exit(0) | |
} | |
/** | |
* File path file | |
*/ | |
const filePath = process.argv[2] | |
// Check if file exists | |
if (!fs.existsSync(filePath)) { | |
console.error(`File was not found: "${colors.red(filePath)}"\n`) | |
helpOutput() | |
process.exit(1) | |
} | |
/** | |
* Regex to find image resources | |
* ```js | |
* const aString = '<img src="@attachment/test.svg" >' + | |
* '<img src="@attachment/test.png">' | |
* let match = regexImageResource.exec(aString) | |
* while (match !== null) { | |
* // <img src="@attachment/test.svg" >, <img src="@attachment/test.png" > | |
* console.log(match[1]) | |
* match = regexImageResource.exec(aString) | |
* } | |
* ``` | |
*/ | |
const regexImageResource = /<img .*src="@attachment\/.*?".*>/g | |
/** | |
* Extract all matches from the file via a fs.stream (much faster | |
* when executing on large files) | |
* @param {string} filePath File that should be read | |
* @returns {Promise<Buffer>} Array with buffer for file to edit | |
*/ | |
async function createdBufferFromFileViaStream (filePath) { | |
return new Promise((resolve, reject) => { | |
const label = `createdBufferFromFileViaStream (${filePath})` | |
if (enableInfo) { console.time(label) } | |
let buffer = null | |
const stream = fs.createReadStream(filePath, { encoding: 'utf8' }) | |
stream.on('data', data => { | |
buffer = Buffer.from(data | |
.replace(regexImageResource, | |
(everything) => everything.replace(/@attachment/g, replaceWith)) | |
// Remove notable information (if found at the top) | |
.replace(/^---[\s\S]*?---[\s]*/m, '')) | |
stream.destroy() | |
}).on('error', err => { | |
if (enableInfo) { console.timeEnd(label) } | |
reject(err) | |
}).on('close', () => { | |
if (enableInfo) { console.timeEnd(label) } | |
resolve(buffer) | |
}) | |
}) | |
} | |
/** | |
* Write file | |
* @param {string} filePath | |
* @param {Buffer} buffer | |
*/ | |
async function writeToFile (filePath, buffer) { | |
return new Promise((resolve, reject) => { | |
const label = `writeBufferToNewFile (${filePath})` | |
if (enableInfo) { console.time(label) } | |
fs.open(filePath, 'w', function (err, fd) { | |
if (err) { | |
if (enableInfo) { console.timeEnd(label) } | |
return reject(err) | |
} | |
fs.write(fd, buffer, 0, buffer.length, () => { }, (err) => { | |
if (err) { | |
if (enableInfo) { console.timeEnd(label) } | |
return reject(err) | |
} | |
fs.close(fd, () => { | |
if (enableInfo) { console.timeEnd(label) } | |
resolve() | |
}) | |
}) | |
}) | |
}) | |
} | |
// MAIN | |
// Create new file for use in Typora | |
createdBufferFromFileViaStream(filePath) | |
.then(buffer => { | |
const newFilePath = path.join(path.dirname(filePath), | |
path.basename(filePath, path.extname(filePath)) + | |
'_typora' + path.extname(filePath)) | |
writeToFile(newFilePath, buffer).then(() => { | |
console.log(`File was written: "${newFilePath}"`) | |
}).catch(console.error) | |
}) | |
.catch(console.error) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Description: | |
Scraps Markdown note created with Notable for used resources to | |
edit it and export it to a new file that can be edited in Typora. | |
Example: | |
$ node .\notableNoteToTypora.js filePath.md -enableOptionalOption | |
File was written: "filePath_typora.md" | |
Options: | |
-info Get information about performance | |
and other things | |
-customReplace "attachmentsDir" Replace "@attachment" in img tags | |
with a custom string |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment