1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 01:36:22 +00:00

Merge branch 'master' into export-yfm

This commit is contained in:
Baptiste Augrain
2020-06-12 15:17:02 +02:00
327 changed files with 21961 additions and 12973 deletions

View File

@@ -16,7 +16,7 @@ const CSON = require('@rokt33r/season')
* 3. fetch notes & folders
* 4. return `{storage: {...} folders: [folder]}`
*/
function addStorage (input) {
function addStorage(input) {
if (!_.isString(input.path)) {
return Promise.reject(new Error('Path must be a string.'))
}
@@ -29,7 +29,7 @@ function addStorage (input) {
rawStorages = []
}
let key = keygen()
while (rawStorages.some((storage) => storage.key === key)) {
while (rawStorages.some(storage => storage.key === key)) {
key = keygen()
}
@@ -43,7 +43,7 @@ function addStorage (input) {
return Promise.resolve(newStorage)
.then(resolveStorageData)
.then(function saveMetadataToLocalStorage (resolvedStorage) {
.then(function saveMetadataToLocalStorage(resolvedStorage) {
newStorage = resolvedStorage
rawStorages.push({
key: newStorage.key,
@@ -56,27 +56,29 @@ function addStorage (input) {
localStorage.setItem('storages', JSON.stringify(rawStorages))
return newStorage
})
.then(function (storage) {
return resolveStorageNotes(storage)
.then((notes) => {
let unknownCount = 0
notes.forEach((note) => {
if (!storage.folders.some((folder) => note.folder === folder.key)) {
unknownCount++
storage.folders.push({
key: note.folder,
color: consts.FOLDER_COLORS[(unknownCount - 1) % 7],
name: 'Unknown ' + unknownCount
})
}
})
if (unknownCount > 0) {
CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['folders', 'version']))
.then(function(storage) {
return resolveStorageNotes(storage).then(notes => {
let unknownCount = 0
notes.forEach(note => {
if (!storage.folders.some(folder => note.folder === folder.key)) {
unknownCount++
storage.folders.push({
key: note.folder,
color: consts.FOLDER_COLORS[(unknownCount - 1) % 7],
name: 'Unknown ' + unknownCount
})
}
return notes
})
if (unknownCount > 0) {
CSON.writeFileSync(
path.join(storage.path, 'boostnote.json'),
_.pick(storage, ['folders', 'version'])
)
}
return notes
})
})
.then(function returnValue (notes) {
.then(function returnValue(notes) {
return {
storage: newStorage,
notes

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ import path from 'path'
* @param {String} dstPath
* @return {Promise} an image path
*/
function copyFile (srcPath, dstPath) {
function copyFile(srcPath, dstPath) {
if (!path.extname(dstPath)) {
dstPath = path.join(dstPath, path.basename(srcPath))
}

View File

@@ -22,7 +22,7 @@ const { findStorage } = require('browser/lib/findStorage')
* }
* ```
*/
function createFolder (storageKey, input) {
function createFolder(storageKey, input) {
let targetStorage
try {
if (input == null) throw new Error('No input found.')
@@ -34,26 +34,28 @@ function createFolder (storageKey, input) {
return Promise.reject(e)
}
return resolveStorageData(targetStorage)
.then(function createFolder (storage) {
let key = keygen()
while (storage.folders.some((folder) => folder.key === key)) {
key = keygen()
}
const newFolder = {
key,
color: input.color,
name: input.name
}
return resolveStorageData(targetStorage).then(function createFolder(storage) {
let key = keygen()
while (storage.folders.some(folder => folder.key === key)) {
key = keygen()
}
const newFolder = {
key,
color: input.color,
name: input.name
}
storage.folders.push(newFolder)
storage.folders.push(newFolder)
CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['folders', 'version']))
CSON.writeFileSync(
path.join(storage.path, 'boostnote.json'),
_.pick(storage, ['folders', 'version'])
)
return {
storage
}
})
return {
storage
}
})
}
module.exports = createFolder

View File

@@ -6,9 +6,11 @@ const path = require('path')
const CSON = require('@rokt33r/season')
const { findStorage } = require('browser/lib/findStorage')
function validateInput (input) {
function validateInput(input) {
if (!_.isArray(input.tags)) input.tags = []
input.tags = input.tags.filter((tag) => _.isString(tag) && tag.trim().length > 0)
input.tags = input.tags.filter(
tag => _.isString(tag) && tag.trim().length > 0
)
if (!_.isString(input.title)) input.title = ''
input.isStarred = !!input.isStarred
input.isTrashed = !!input.isTrashed
@@ -21,20 +23,24 @@ function validateInput (input) {
case 'SNIPPET_NOTE':
if (!_.isString(input.description)) input.description = ''
if (!_.isArray(input.snippets)) {
input.snippets = [{
name: '',
mode: 'text',
content: '',
linesHighlighted: []
}]
input.snippets = [
{
name: '',
mode: 'text',
content: '',
linesHighlighted: []
}
]
}
break
default:
throw new Error('Invalid type: only MARKDOWN_NOTE and SNIPPET_NOTE are available.')
throw new Error(
'Invalid type: only MARKDOWN_NOTE and SNIPPET_NOTE are available.'
)
}
}
function createNote (storageKey, input) {
function createNote(storageKey, input) {
let targetStorage
try {
if (input == null) throw new Error('No input found.')
@@ -47,13 +53,13 @@ function createNote (storageKey, input) {
}
return resolveStorageData(targetStorage)
.then(function checkFolderExists (storage) {
if (_.find(storage.folders, {key: input.folder}) == null) {
throw new Error('Target folder doesn\'t exist.')
.then(function checkFolderExists(storage) {
if (_.find(storage.folders, { key: input.folder }) == null) {
throw new Error("Target folder doesn't exist.")
}
return storage
})
.then(function saveNote (storage) {
.then(function saveNote(storage) {
let key = keygen(true)
let isUnique = false
while (!isUnique) {
@@ -68,7 +74,8 @@ function createNote (storageKey, input) {
}
}
}
const noteData = Object.assign({},
const noteData = Object.assign(
{},
{
createdAt: new Date(),
updatedAt: new Date()
@@ -77,9 +84,13 @@ function createNote (storageKey, input) {
{
key,
storage: storageKey
})
}
)
CSON.writeFileSync(path.join(storage.path, 'notes', key + '.cson'), _.omit(noteData, ['key', 'storage']))
CSON.writeFileSync(
path.join(storage.path, 'notes', key + '.cson'),
_.omit(noteData, ['key', 'storage'])
)
return noteData
})

View File

@@ -0,0 +1,102 @@
const http = require('http')
const https = require('https')
const { createTurndownService } = require('../../../lib/turndown')
const createNote = require('./createNote')
import { push } from 'connected-react-router'
import ee from 'browser/main/lib/eventEmitter'
function validateUrl(str) {
if (
/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(
str
)
) {
return true
} else {
return false
}
}
const ERROR_MESSAGES = {
ENOTFOUND:
'URL not found. Please check the URL, or your internet connection and try again.',
VALIDATION_ERROR:
'Please check if the URL follows this format: https://www.google.com',
UNEXPECTED: 'Unexpected error! Please check console for details!'
}
function createNoteFromUrl(
url,
storage,
folder,
dispatch = null,
location = null
) {
return new Promise((resolve, reject) => {
const td = createTurndownService()
if (!validateUrl(url)) {
reject({ result: false, error: ERROR_MESSAGES.VALIDATION_ERROR })
}
const request = url.startsWith('https') ? https : http
const req = request.request(url, res => {
let data = ''
res.on('data', chunk => {
data += chunk
})
res.on('end', () => {
const markdownHTML = td.turndown(data)
if (dispatch !== null) {
createNote(storage, {
type: 'MARKDOWN_NOTE',
folder: folder,
title: '',
content: markdownHTML
}).then(note => {
const noteHash = note.key
dispatch({
type: 'UPDATE_NOTE',
note: note
})
dispatch(
push({
pathname: location.pathname,
query: { key: noteHash }
})
)
ee.emit('list:jump', noteHash)
ee.emit('detail:focus')
resolve({ result: true, error: null })
})
} else {
createNote(storage, {
type: 'MARKDOWN_NOTE',
folder: folder,
title: '',
content: markdownHTML
}).then(note => {
resolve({ result: true, note, error: null })
})
}
})
})
req.on('error', e => {
console.error('error in parsing URL', e)
reject({
result: false,
error: ERROR_MESSAGES[e.code] || ERROR_MESSAGES.UNEXPECTED
})
})
req.end()
})
}
module.exports = createNoteFromUrl

View File

@@ -3,7 +3,7 @@ import crypto from 'crypto'
import consts from 'browser/lib/consts'
import fetchSnippet from 'browser/main/lib/dataApi/fetchSnippet'
function createSnippet (snippetFile) {
function createSnippet(snippetFile) {
return new Promise((resolve, reject) => {
const newSnippet = {
id: crypto.randomBytes(16).toString('hex'),
@@ -12,15 +12,21 @@ function createSnippet (snippetFile) {
content: '',
linesHighlighted: []
}
fetchSnippet(null, snippetFile).then((snippets) => {
snippets.push(newSnippet)
fs.writeFile(snippetFile || consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => {
if (err) reject(err)
resolve(newSnippet)
fetchSnippet(null, snippetFile)
.then(snippets => {
snippets.push(newSnippet)
fs.writeFile(
snippetFile || consts.SNIPPET_FILE,
JSON.stringify(snippets, null, 4),
err => {
if (err) reject(err)
resolve(newSnippet)
}
)
})
.catch(err => {
reject(err)
})
}).catch((err) => {
reject(err)
})
})
}

View File

@@ -3,7 +3,6 @@ const path = require('path')
const resolveStorageData = require('./resolveStorageData')
const resolveStorageNotes = require('./resolveStorageNotes')
const CSON = require('@rokt33r/season')
const sander = require('sander')
const { findStorage } = require('browser/lib/findStorage')
const deleteSingleNote = require('./deleteNote')
@@ -19,7 +18,7 @@ const deleteSingleNote = require('./deleteNote')
* }
* ```
*/
function deleteFolder (storageKey, folderKey) {
function deleteFolder(storageKey, folderKey) {
let targetStorage
try {
targetStorage = findStorage(storageKey)
@@ -28,35 +27,36 @@ function deleteFolder (storageKey, folderKey) {
}
return resolveStorageData(targetStorage)
.then(function assignNotes (storage) {
return resolveStorageNotes(storage)
.then((notes) => {
return {
storage,
notes
}
})
.then(function assignNotes(storage) {
return resolveStorageNotes(storage).then(notes => {
return {
storage,
notes
}
})
})
.then(function deleteFolderAndNotes (data) {
.then(function deleteFolderAndNotes(data) {
const { storage, notes } = data
storage.folders = storage.folders
.filter(function excludeTargetFolder (folder) {
return folder.key !== folderKey
})
storage.folders = storage.folders.filter(function excludeTargetFolder(
folder
) {
return folder.key !== folderKey
})
const targetNotes = notes.filter(function filterTargetNotes (note) {
const targetNotes = notes.filter(function filterTargetNotes(note) {
return note.folder === folderKey
})
const deleteAllNotes = targetNotes
.map(function deleteNote (note) {
return deleteSingleNote(storageKey, note.key)
})
return Promise.all(deleteAllNotes)
.then(() => storage)
const deleteAllNotes = targetNotes.map(function deleteNote(note) {
return deleteSingleNote(storageKey, note.key)
})
return Promise.all(deleteAllNotes).then(() => storage)
})
.then(function (storage) {
CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['folders', 'version']))
.then(function(storage) {
CSON.writeFileSync(
path.join(storage.path, 'boostnote.json'),
_.pick(storage, ['folders', 'version'])
)
return {
storage,

View File

@@ -4,7 +4,7 @@ const sander = require('sander')
const attachmentManagement = require('./attachmentManagement')
const { findStorage } = require('browser/lib/findStorage')
function deleteNote (storageKey, noteKey) {
function deleteNote(storageKey, noteKey) {
let targetStorage
try {
targetStorage = findStorage(storageKey)
@@ -13,7 +13,7 @@ function deleteNote (storageKey, noteKey) {
}
return resolveStorageData(targetStorage)
.then(function deleteNoteFile (storage) {
.then(function deleteNoteFile(storage) {
const notePath = path.join(storage.path, 'notes', noteKey + '.cson')
try {
@@ -26,8 +26,11 @@ function deleteNote (storageKey, noteKey) {
storageKey
}
})
.then(function deleteAttachments (storageInfo) {
attachmentManagement.deleteAttachmentFolder(storageInfo.storageKey, storageInfo.noteKey)
.then(function deleteAttachments(storageInfo) {
attachmentManagement.deleteAttachmentFolder(
storageInfo.storageKey,
storageInfo.noteKey
)
return storageInfo
})
}

View File

@@ -2,14 +2,20 @@ import fs from 'fs'
import consts from 'browser/lib/consts'
import fetchSnippet from 'browser/main/lib/dataApi/fetchSnippet'
function deleteSnippet (snippet, snippetFile) {
function deleteSnippet(snippet, snippetFile) {
return new Promise((resolve, reject) => {
fetchSnippet(null, snippetFile).then((snippets) => {
snippets = snippets.filter(currentSnippet => currentSnippet.id !== snippet.id)
fs.writeFile(snippetFile || consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => {
if (err) reject(err)
resolve(snippet)
})
fetchSnippet(null, snippetFile).then(snippets => {
snippets = snippets.filter(
currentSnippet => currentSnippet.id !== snippet.id
)
fs.writeFile(
snippetFile || consts.SNIPPET_FILE,
JSON.stringify(snippets, null, 4),
err => {
if (err) reject(err)
resolve(snippet)
}
)
})
})
}

View File

@@ -4,8 +4,7 @@ import resolveStorageNotes from './resolveStorageNotes'
import filenamify from 'filenamify'
import path from 'path'
import exportNote from './exportNote'
import formatMarkdown from './formatMarkdown'
import formatHTML from './formatHTML'
import getContentFormatter from './getContentFormatter'
/**
* @param {String} storageKey
@@ -25,7 +24,7 @@ import formatHTML from './formatHTML'
* ```
*/
function exportFolder (storageKey, folderKey, fileType, exportDir, config) {
function exportFolder(storageKey, folderKey, fileType, exportDir, config) {
let targetStorage
try {
targetStorage = findStorage(storageKey)
@@ -37,48 +36,32 @@ function exportFolder (storageKey, folderKey, fileType, exportDir, config) {
.then(storage => {
return resolveStorageNotes(storage).then(notes => ({
storage,
notes: notes.filter(note => note.folder === folderKey && !note.isTrashed && note.type === 'MARKDOWN_NOTE')
notes: notes.filter(
note =>
note.folder === folderKey &&
!note.isTrashed &&
note.type === 'MARKDOWN_NOTE'
)
}))
})
.then(({ storage, notes }) => {
let contentFormatter = null
if (fileType === 'md') {
contentFormatter = formatMarkdown({
storagePath: storage.path,
export: config.export
})
} else if (fileType === 'html') {
contentFormatter = formatHTML({
theme: config.ui.theme,
fontSize: config.preview.fontSize,
fontFamily: config.preview.fontFamily,
codeBlockTheme: config.preview.codeBlockTheme,
codeBlockFontFamily: config.editor.fontFamily,
lineNumber: config.preview.lineNumber,
indentSize: config.editor.indentSize,
scrollPastEnd: config.preview.scrollPastEnd,
smartQuotes: config.preview.smartQuotes,
breaks: config.preview.breaks,
sanitize: config.preview.sanitize,
customCSS: config.preview.customCSS,
allowCustomCSS: config.preview.allowCustomCSS,
storagePath: storage.path,
export: config.export
})
}
const contentFormatter = getContentFormatter(storage, fileType, config)
return Promise
.all(notes.map(note => {
const targetPath = path.join(exportDir, `${filenamify(note.title, {replacement: '_'})}.${fileType}`)
return Promise.all(
notes.map(note => {
const targetPath = path.join(
exportDir,
`${filenamify(note.title, { replacement: '_' })}.${fileType}`
)
return exportNote(storage.key, note, targetPath, contentFormatter)
}))
.then(() => ({
storage,
folderKey,
fileType,
exportDir
}))
})
).then(() => ({
storage,
folderKey,
fileType,
exportDir
}))
})
}

View File

@@ -4,8 +4,6 @@ import { findStorage } from 'browser/lib/findStorage'
const fs = require('fs')
const path = require('path')
const attachmentManagement = require('./attachmentManagement')
/**
* Export note together with attachments
*
@@ -18,31 +16,38 @@ const attachmentManagement = require('./attachmentManagement')
* @param {function} outputFormatter
* @return {Promise.<*[]>}
*/
function exportNote (storageKey, note, targetPath, outputFormatter) {
const storagePath = path.isAbsolute(storageKey) ? storageKey : findStorage(storageKey).path
function exportNote(storageKey, note, targetPath, outputFormatter) {
const storagePath = path.isAbsolute(storageKey)
? storageKey
: findStorage(storageKey).path
const exportTasks = []
if (!storagePath) {
throw new Error('Storage path is not found')
}
const exportedData = outputFormatter ? outputFormatter(note, targetPath, exportTasks) : note.content
const exportedData = Promise.resolve(
outputFormatter
? outputFormatter(note, targetPath, exportTasks)
: note.content
)
const tasks = prepareTasks(exportTasks, storagePath, path.dirname(targetPath))
return Promise
.all(tasks.map(task => copyFile(task.src, task.dst)))
.then(() => {
return saveToFile(exportedData, targetPath)
})
.catch(error => {
rollbackExport(tasks)
throw error
})
return Promise.all(tasks.map(task => copyFile(task.src, task.dst)))
.then(() => exportedData)
.then(data => {
return saveToFile(data, targetPath)
})
.catch(error => {
rollbackExport(tasks)
throw error
})
}
function prepareTasks (tasks, storagePath, targetPath) {
return tasks.map((task) => {
function prepareTasks(tasks, storagePath, targetPath) {
return tasks.map(task => {
if (!path.isAbsolute(task.src)) {
task.src = path.join(storagePath, task.src)
}
@@ -55,14 +60,12 @@ function prepareTasks (tasks, storagePath, targetPath) {
})
}
function saveToFile (data, filename) {
function saveToFile(data, filename) {
return new Promise((resolve, reject) => {
fs.writeFile(filename, data, error => {
if (error) {
reject(error)
} else {
resolve(filename)
}
fs.writeFile(filename, data, err => {
if (err) return reject(err)
resolve(filename)
})
})
}
@@ -71,9 +74,9 @@ function saveToFile (data, filename) {
* Remove exported files
* @param tasks Array of copy task objects. Object consists of two mandatory fields `src` and `dst`
*/
function rollbackExport (tasks) {
function rollbackExport(tasks) {
const folders = new Set()
tasks.forEach((task) => {
tasks.forEach(task => {
let fullpath = task.dst
if (!path.extname(task.dst)) {
@@ -86,7 +89,7 @@ function rollbackExport (tasks) {
}
})
folders.forEach((folder) => {
folders.forEach(folder => {
if (fs.readdirSync(folder).length === 0) {
fs.rmdirSync(folder)
}

View File

@@ -1,7 +1,6 @@
import { findStorage } from 'browser/lib/findStorage'
import exportNote from './exportNote'
import formatMarkdown from './formatMarkdown'
import formatHTML from './formatHTML'
import getContentFormatter from './getContentFormatter'
/**
* @param {Object} note
@@ -10,34 +9,9 @@ import formatHTML from './formatHTML'
* @param {Object} config
*/
function exportNoteAs (note, filename, fileType, config) {
function exportNoteAs(note, filename, fileType, config) {
const storage = findStorage(note.storage)
let contentFormatter = null
if (fileType === 'md') {
contentFormatter = formatMarkdown({
storagePath: storage.path,
export: config.export
})
} else if (fileType === 'html') {
contentFormatter = formatHTML({
theme: config.ui.theme,
fontSize: config.preview.fontSize,
fontFamily: config.preview.fontFamily,
codeBlockTheme: config.preview.codeBlockTheme,
codeBlockFontFamily: config.editor.fontFamily,
lineNumber: config.preview.lineNumber,
indentSize: config.editor.indentSize,
scrollPastEnd: config.preview.scrollPastEnd,
smartQuotes: config.preview.smartQuotes,
breaks: config.preview.breaks,
sanitize: config.preview.sanitize,
customCSS: config.preview.customCSS,
allowCustomCSS: config.preview.allowCustomCSS,
storagePath: storage.path,
export: config.export
})
}
const contentFormatter = getContentFormatter(storage, fileType, config)
return exportNote(storage.key, note, filename, contentFormatter)
}

View File

@@ -24,7 +24,7 @@ import formatHTML from './formatHTML'
* ```
*/
function exportStorage (storageKey, fileType, exportDir, config) {
function exportStorage(storageKey, fileType, exportDir, config) {
let targetStorage
try {
targetStorage = findStorage(storageKey)
@@ -36,7 +36,9 @@ function exportStorage (storageKey, fileType, exportDir, config) {
.then(storage => {
return resolveStorageNotes(storage).then(notes => ({
storage,
notes: notes.filter(note => !note.isTrashed && note.type === 'MARKDOWN_NOTE')
notes: notes.filter(
note => !note.isTrashed && note.type === 'MARKDOWN_NOTE'
)
}))
})
.then(({ storage, notes }) => {
@@ -68,7 +70,10 @@ function exportStorage (storageKey, fileType, exportDir, config) {
const folderNamesMapping = {}
storage.folders.forEach(folder => {
const folderExportedDir = path.join(exportDir, filenamify(folder.name, {replacement: '_'}))
const folderExportedDir = path.join(
exportDir,
filenamify(folder.name, { replacement: '_' })
)
folderNamesMapping[folder.key] = folderExportedDir
@@ -78,17 +83,20 @@ function exportStorage (storageKey, fileType, exportDir, config) {
} catch (e) {}
})
return Promise
.all(notes.map(note => {
const targetPath = path.join(folderNamesMapping[note.folder], `${filenamify(note.title, {replacement: '_'})}.${fileType}`)
return Promise.all(
notes.map(note => {
const targetPath = path.join(
folderNamesMapping[note.folder],
`${filenamify(note.title, { replacement: '_' })}.${fileType}`
)
return exportNote(storage.key, note, targetPath, contentFormatter)
}))
.then(() => ({
storage,
fileType,
exportDir
}))
})
).then(() => ({
storage,
fileType,
exportDir
}))
})
}

View File

@@ -1,7 +1,7 @@
import fs from 'fs'
import consts from 'browser/lib/consts'
function fetchSnippet (id, snippetFile) {
function fetchSnippet(id, snippetFile) {
return new Promise((resolve, reject) => {
fs.readFile(snippetFile || consts.SNIPPET_FILE, 'utf8', (err, data) => {
if (err) {
@@ -9,7 +9,9 @@ function fetchSnippet (id, snippetFile) {
}
const snippets = JSON.parse(data)
if (id) {
const snippet = snippets.find(snippet => { return snippet.id === id })
const snippet = snippets.find(snippet => {
return snippet.id === id
})
resolve(snippet)
}
resolve(snippets)

View File

@@ -5,9 +5,12 @@ import { remote } from 'electron'
import consts from 'browser/lib/consts'
import Markdown from 'browser/lib/markdown'
import attachmentManagement from './attachmentManagement'
import { version as codemirrorVersion } from 'codemirror/package.json'
const { app } = remote
const appPath = fileUrl(process.env.NODE_ENV === 'production' ? app.getAppPath() : path.resolve())
const appPath = fileUrl(
process.env.NODE_ENV === 'production' ? app.getAppPath() : path.resolve()
)
let markdownStyle = ''
try {
@@ -16,11 +19,14 @@ try {
export const CSS_FILES = [
`${appPath}/node_modules/katex/dist/katex.min.css`,
`${appPath}/node_modules/codemirror/lib/codemirror.css`
`${appPath}/node_modules/codemirror/lib/codemirror.css`,
`${appPath}/node_modules/react-image-carousel/lib/css/main.min.css`
]
const macos = global.process.platform === 'darwin'
const defaultFontFamily = ['helvetica', 'arial', 'sans-serif']
if (global.process.platform !== 'darwin') {
if (!macos) {
defaultFontFamily.unshift('Microsoft YaHei')
defaultFontFamily.unshift('meiryo')
}
@@ -34,7 +40,7 @@ const defaultCodeBlockFontFamily = [
'monospace'
]
function unprefix (file) {
function unprefix(file) {
if (global.process.platform === 'win32') {
return file.replace('file:///', '')
} else {
@@ -63,7 +69,7 @@ function unprefix (file) {
* }
* ```
*/
export default function formatHTML (props) {
export default function formatHTML(props) {
const {
fontFamily,
fontSize,
@@ -96,14 +102,16 @@ export default function formatHTML (props) {
const files = [getCodeThemeLink(codeBlockTheme), ...CSS_FILES]
return function (note, targetPath, exportTasks) {
let styles = files.map(file => `<link rel="stylesheet" href="css/${path.basename(file)}">`).join('\n')
return function(note, targetPath, exportTasks) {
const styles = files
.map(file => `<link rel="stylesheet" href="css/${path.basename(file)}">`)
.join('\n')
let inlineScripts = ''
let scripts = ''
let decodeEntities = false
function addDecodeEntities () {
function addDecodeEntities() {
if (decodeEntities) {
return
}
@@ -130,7 +138,7 @@ function decodeEntities (text) {
}
let lodash = false
function addLodash () {
function addLodash() {
if (lodash) {
return
}
@@ -146,7 +154,7 @@ function decodeEntities (text) {
}
let raphael = false
function addRaphael () {
function addRaphael() {
if (raphael) {
return
}
@@ -162,7 +170,7 @@ function decodeEntities (text) {
}
let yaml = false
function addYAML () {
function addYAML() {
if (yaml) {
return
}
@@ -178,7 +186,7 @@ function decodeEntities (text) {
}
let chart = false
function addChart () {
function addChart() {
if (chart) {
return
}
@@ -195,7 +203,7 @@ function decodeEntities (text) {
scripts += `<script src="js/Chart.min.js"></script>`
inlineScripts += `
function displayCharts () {
function displayCharts() {
_.forEach(
document.querySelectorAll('.chart'),
el => {
@@ -227,7 +235,7 @@ document.addEventListener('DOMContentLoaded', displayCharts);
}
let codemirror = false
function addCodeMirror () {
function addCodeMirror() {
if (codemirror) {
return
}
@@ -237,19 +245,28 @@ document.addEventListener('DOMContentLoaded', displayCharts);
addDecodeEntities()
addLodash()
exportTasks.push({
src: unprefix(`${appPath}/node_modules/codemirror/lib/codemirror.js`),
dst: 'js/codemirror'
}, {
src: unprefix(`${appPath}/node_modules/codemirror/mode/meta.js`),
dst: 'js/codemirror/mode'
}, {
src: unprefix(`${appPath}/node_modules/codemirror/addon/mode/loadmode.js`),
dst: 'js/codemirror/addon/mode'
}, {
src: unprefix(`${appPath}/node_modules/codemirror/addon/runmode/runmode.js`),
dst: 'js/codemirror/addon/runmode'
})
exportTasks.push(
{
src: unprefix(`${appPath}/node_modules/codemirror/lib/codemirror.js`),
dst: 'js/codemirror'
},
{
src: unprefix(`${appPath}/node_modules/codemirror/mode/meta.js`),
dst: 'js/codemirror/mode'
},
{
src: unprefix(
`${appPath}/node_modules/codemirror/addon/mode/loadmode.js`
),
dst: 'js/codemirror/addon/mode'
},
{
src: unprefix(
`${appPath}/node_modules/codemirror/addon/runmode/runmode.js`
),
dst: 'js/codemirror/addon/runmode'
}
)
scripts += `
<script src="js/codemirror/codemirror.js"></script>
@@ -265,18 +282,18 @@ document.addEventListener('DOMContentLoaded', displayCharts);
}
inlineScripts += `
CodeMirror.modeURL = 'js/codemirror/mode/%N/%N.js';
CodeMirror.modeURL = 'https://cdn.jsdelivr.net/npm/codemirror@${codemirrorVersion}/mode/%N/%N.js';
function displayCodeBlocks () {
function displayCodeBlocks() {
_.forEach(
document.querySelectorAll('.code code'),
el => {
el.parentNode.className += ' ${className}'
let syntax = CodeMirror.findModeByName(el.className)
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
CodeMirror.requireMode(syntax.mode, () => {
const content = decodeEntities(el.innerHTML)
el.innerHTML = ''
el.parentNode.className += ' ${className}'
CodeMirror.runMode(content, syntax.mime, el, {
tabSize: ${indentSize}
})
@@ -290,7 +307,7 @@ document.addEventListener('DOMContentLoaded', displayCodeBlocks);
}
let flowchart = false
function addFlowchart () {
function addFlowchart() {
if (flowchart) {
return
}
@@ -302,14 +319,16 @@ document.addEventListener('DOMContentLoaded', displayCodeBlocks);
addRaphael()
exportTasks.push({
src: unprefix(`${appPath}/node_modules/flowchart.js/release/flowchart.min.js`),
src: unprefix(
`${appPath}/node_modules/flowchart.js/release/flowchart.min.js`
),
dst: 'js'
})
scripts += `<script src="js/flowchart.min.js"></script>`
inlineScripts += `
function displayFlowcharts () {
function displayFlowcharts() {
_.forEach(
document.querySelectorAll('.flowchart'),
el => {
@@ -332,7 +351,7 @@ document.addEventListener('DOMContentLoaded', displayFlowcharts);
}
let mermaid = false
function addMermaid () {
function addMermaid() {
if (mermaid) {
return
}
@@ -348,10 +367,8 @@ document.addEventListener('DOMContentLoaded', displayFlowcharts);
scripts += `<script src="js/mermaid.min.js"></script>`
const isDarkTheme = theme === 'dark' || theme === 'solarized-dark' || theme === 'monokai' || theme === 'dracula'
inlineScripts += `
function displayMermaids () {
function displayMermaids() {
_.forEach(
document.querySelectorAll('.mermaid'),
el => {
@@ -368,7 +385,7 @@ document.addEventListener('DOMContentLoaded', displayMermaids);
}
let sequence = false
function addSequence () {
function addSequence() {
if (sequence) {
return
}
@@ -380,14 +397,16 @@ document.addEventListener('DOMContentLoaded', displayMermaids);
addRaphael()
exportTasks.push({
src: unprefix(`${appPath}/node_modules/js-sequence-diagrams/fucknpm/sequence-diagram-min.js`),
src: unprefix(
`${appPath}/node_modules/@rokt33r/js-sequence-diagrams/dist/sequence-diagram-min.js`
),
dst: 'js'
})
scripts += `<script src="js/sequence-diagram-min.js"></script>`
inlineScripts += `
function displaySequences () {
function displaySequences() {
_.forEach(
document.querySelectorAll('.sequence'),
el => {
@@ -414,7 +433,7 @@ document.addEventListener('DOMContentLoaded', displaySequences);
typographer: smartQuotes,
sanitize,
breaks,
onFence (type, mode) {
onFence(type, mode) {
if (type === 'chart') {
addChart()
@@ -425,7 +444,9 @@ document.addEventListener('DOMContentLoaded', displaySequences);
addCodeMirror()
if (mode && modes[mode] !== true) {
const file = unprefix(`${appPath}/node_modules/codemirror/mode/${mode}/${mode}.js`)
const file = unprefix(
`${appPath}/node_modules/codemirror/mode/${mode}/${mode}.js`
)
if (fs.existsSync(file)) {
exportTasks.push({
@@ -448,7 +469,10 @@ document.addEventListener('DOMContentLoaded', displaySequences);
let body = markdown.render(note.content)
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(note.content, props.storagePath)
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(
note.content,
props.storagePath
)
files.forEach(file => {
exportTasks.push({
@@ -457,7 +481,11 @@ document.addEventListener('DOMContentLoaded', displaySequences);
})
})
const destinationFolder = props.export.prefixAttachmentFolder ? `${path.parse(targetPath).name} - ${attachmentManagement.DESTINATION_FOLDER}` : attachmentManagement.DESTINATION_FOLDER
const destinationFolder = props.export.prefixAttachmentFolder
? `${path.parse(targetPath).name} - ${
attachmentManagement.DESTINATION_FOLDER
}`
: attachmentManagement.DESTINATION_FOLDER
attachmentsAbsolutePaths.forEach(attachment => {
exportTasks.push({
@@ -466,7 +494,11 @@ document.addEventListener('DOMContentLoaded', displaySequences);
})
})
body = attachmentManagement.replaceStorageReferences(body, note.key, destinationFolder)
body = attachmentManagement.replaceStorageReferences(
body,
note.key,
destinationFolder
)
return `
<html>
@@ -478,7 +510,7 @@ document.addEventListener('DOMContentLoaded', displaySequences);
${scripts}
<script>${inlineScripts}</script>
</head>
<body>
<body data-theme="${theme}">
${body}
</body>
</html>
@@ -486,7 +518,7 @@ ${body}
}
}
export function getStyleParams (props) {
export function getStyleParams(props) {
const {
fontSize,
lineNumber,
@@ -494,25 +526,27 @@ export function getStyleParams (props) {
scrollPastEnd,
theme,
allowCustomCSS,
customCSS
customCSS,
RTL
} = props
let { fontFamily, codeBlockFontFamily } = props
fontFamily = _.isString(fontFamily) && fontFamily.trim().length > 0
? fontFamily
.split(',')
.map(fontName => fontName.trim())
.concat(defaultFontFamily)
: defaultFontFamily
fontFamily =
_.isString(fontFamily) && fontFamily.trim().length > 0
? fontFamily
.split(',')
.map(fontName => fontName.trim())
.concat(defaultFontFamily)
: defaultFontFamily
codeBlockFontFamily = _.isString(codeBlockFontFamily) &&
codeBlockFontFamily.trim().length > 0
? codeBlockFontFamily
.split(',')
.map(fontName => fontName.trim())
.concat(defaultCodeBlockFontFamily)
: defaultCodeBlockFontFamily
codeBlockFontFamily =
_.isString(codeBlockFontFamily) && codeBlockFontFamily.trim().length > 0
? codeBlockFontFamily
.split(',')
.map(fontName => fontName.trim())
.concat(defaultCodeBlockFontFamily)
: defaultCodeBlockFontFamily
return {
fontFamily,
@@ -523,21 +557,20 @@ export function getStyleParams (props) {
scrollPastEnd,
theme,
allowCustomCSS,
customCSS
customCSS,
RTL
}
}
export function getCodeThemeLink (theme) {
if (consts.THEMES.some(_theme => _theme === theme)) {
theme = theme !== 'default' ? theme : 'elegant'
}
export function getCodeThemeLink(name) {
const theme = consts.THEMES.find(theme => theme.name === name)
return theme.startsWith('solarized')
? `${appPath}/node_modules/codemirror/theme/solarized.css`
: `${appPath}/node_modules/codemirror/theme/${theme}.css`
return theme != null
? theme.path
: `${appPath}/node_modules/codemirror/theme/elegant.css`
}
export function buildStyle (
export function buildStyle(
fontFamily,
fontSize,
codeBlockFontFamily,
@@ -545,7 +578,8 @@ export function buildStyle (
scrollPastEnd,
theme,
allowCustomCSS,
customCSS
customCSS,
RTL
) {
return `
@font-face {
@@ -581,17 +615,96 @@ ${markdownStyle}
body {
font-family: '${fontFamily.join("','")}';
font-size: ${fontSize}px;
${scrollPastEnd && 'padding-bottom: 90vh;'}
${scrollPastEnd && 'padding-bottom: 90vh;box-sizing: border-box;'}
${RTL && 'direction: rtl;text-align: right;'}
}
@media print {
body {
padding-bottom: initial;
}
}
code {
font-family: '${codeBlockFontFamily.join("','")}';
background-color: rgba(0,0,0,0.04);
text-align: left;
direction: ltr;
}
p code,
li code,
td code
{
padding: 2px;
border-width: 1px;
border-style: solid;
border-radius: 5px;
}
[data-theme="default"] p code,
[data-theme="default"] li code,
[data-theme="default"] td code
{
background-color: #F4F4F4;
border-color: #d9d9d9;
color: inherit;
}
[data-theme="white"] p code,
[data-theme="white"] li code,
[data-theme="white"] td code
{
background-color: #F4F4F4;
border-color: #d9d9d9;
color: inherit;
}
[data-theme="dark"] p code,
[data-theme="dark"] li code,
[data-theme="dark"] td code
{
background-color: #444444;
border-color: #555;
color: #FFFFFF;
}
[data-theme="dracula"] p code,
[data-theme="dracula"] li code,
[data-theme="dracula"] td code
{
background-color: #444444;
border-color: #555;
color: #FFFFFF;
}
[data-theme="monokai"] p code,
[data-theme="monokai"] li code,
[data-theme="monokai"] td code
{
background-color: #444444;
border-color: #555;
color: #FFFFFF;
}
[data-theme="nord"] p code,
[data-theme="nord"] li code,
[data-theme="nord"] td code
{
background-color: #444444;
border-color: #555;
color: #FFFFFF;
}
[data-theme="solarized-dark"] p code,
[data-theme="solarized-dark"] li code,
[data-theme="solarized-dark"] td code
{
background-color: #444444;
border-color: #555;
color: #FFFFFF;
}
[data-theme="vulcan"] p code,
[data-theme="vulcan"] li code,
[data-theme="vulcan"] td code
{
background-color: #444444;
border-color: #555;
color: #FFFFFF;
}
.lineNumber {
${lineNumber && 'display: block !important;'}
font-family: '${codeBlockFontFamily.join("','")}';

View File

@@ -12,14 +12,21 @@ const delimiterRegExp = /^\-{3}/
* }
* ```
*/
export default function formatMarkdown (props) {
return function (note, targetPath, exportTasks) {
export default function formatMarkdown(props) {
return function(note, targetPath, exportTasks) {
let result = note.content
if (props.storagePath && note.key) {
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(result, props.storagePath)
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(
result,
props.storagePath
)
const destinationFolder = props.export.prefixAttachmentFolder ? `${path.parse(targetPath).name} - ${attachmentManagement.DESTINATION_FOLDER}` : attachmentManagement.DESTINATION_FOLDER
const destinationFolder = props.export.prefixAttachmentFolder
? `${path.parse(targetPath).name} - ${
attachmentManagement.DESTINATION_FOLDER
}`
: attachmentManagement.DESTINATION_FOLDER
attachmentsAbsolutePaths.forEach(attachment => {
exportTasks.push({
@@ -28,7 +35,11 @@ export default function formatMarkdown (props) {
})
})
result = attachmentManagement.replaceStorageReferences(result, note.key, destinationFolder)
result = attachmentManagement.replaceStorageReferences(
result,
note.key,
destinationFolder
)
}
if (props.export.metadata === 'MERGE_HEADER') {
@@ -65,13 +76,12 @@ export default function formatMarkdown (props) {
}
}
function getFrontMatter (markdown) {
function getFrontMatter(markdown) {
const lines = markdown.split('\n')
if (delimiterRegExp.test(lines[0])) {
let line = 0
while (++line < lines.length && !delimiterRegExp.test(lines[line])) {
}
while (++line < lines.length && !delimiterRegExp.test(lines[line])) {}
return yaml.load(lines.slice(1, line).join('\n')) || {}
} else {
@@ -79,13 +89,12 @@ function getFrontMatter (markdown) {
}
}
function replaceFrontMatter (markdown, metadata) {
function replaceFrontMatter(markdown, metadata) {
const lines = markdown.split('\n')
if (delimiterRegExp.test(lines[0])) {
let line = 0
while (++line < lines.length && !delimiterRegExp.test(lines[line])) {
}
while (++line < lines.length && !delimiterRegExp.test(lines[line])) {}
return `---\n${yaml.dump(metadata)}---\n${lines.slice(line + 1).join('\n')}`
} else {

View File

@@ -0,0 +1,26 @@
import formatHTML from './formatHTML'
import { remote } from 'electron'
export default function formatPDF(props) {
return function(note, targetPath, exportTasks) {
const printout = new remote.BrowserWindow({
show: false,
webPreferences: { webSecurity: false, javascript: false }
})
printout.loadURL(
'data:text/html;charset=UTF-8,' +
formatHTML(props)(note, targetPath, exportTasks)
)
return new Promise((resolve, reject) => {
printout.webContents.on('did-finish-load', () => {
printout.webContents.printToPDF({}, (err, data) => {
if (err) reject(err)
else resolve(data)
printout.destroy()
})
})
})
}
}

View File

@@ -0,0 +1,58 @@
import formatMarkdown from './formatMarkdown'
import formatHTML from './formatHTML'
import formatPDF from './formatPDF'
/**
* @param {Object} storage
* @param {String} fileType
* @param {Object} config
*/
export default function getContentFormatterr(storage, fileType, config) {
if (fileType === 'md') {
return formatMarkdown({
storagePath: storage.path,
export: config.export
})
} else if (fileType === 'html') {
return formatHTML({
theme: config.ui.theme,
fontSize: config.preview.fontSize,
fontFamily: config.preview.fontFamily,
codeBlockTheme: config.preview.codeBlockTheme,
codeBlockFontFamily: config.editor.fontFamily,
lineNumber: config.preview.lineNumber,
indentSize: config.editor.indentSize,
scrollPastEnd: config.preview.scrollPastEnd,
smartQuotes: config.preview.smartQuotes,
breaks: config.preview.breaks,
sanitize: config.preview.sanitize,
customCSS: config.preview.customCSS,
allowCustomCSS: config.preview.allowCustomCSS,
storagePath: storage.path,
export: config.export,
RTL: config.editor.rtlEnabled /* && this.state.RTL */
})
} else if (fileType === 'pdf') {
return formatPDF({
theme: config.ui.theme,
fontSize: config.preview.fontSize,
fontFamily: config.preview.fontFamily,
codeBlockTheme: config.preview.codeBlockTheme,
codeBlockFontFamily: config.editor.fontFamily,
lineNumber: config.preview.lineNumber,
indentSize: config.editor.indentSize,
scrollPastEnd: config.preview.scrollPastEnd,
smartQuotes: config.preview.smartQuotes,
breaks: config.preview.breaks,
sanitize: config.preview.sanitize,
customCSS: config.preview.customCSS,
allowCustomCSS: config.preview.allowCustomCSS,
storagePath: storage.path,
export: config.export,
RTL: config.editor.rtlEnabled /* && this.state.RTL */
})
}
return null
}

View File

@@ -11,6 +11,7 @@ const dataApi = {
exportFolder: require('./exportFolder'),
exportStorage: require('./exportStorage'),
createNote: require('./createNote'),
createNoteFromUrl: require('./createNoteFromUrl'),
updateNote: require('./updateNote'),
deleteNote: require('./deleteNote'),
moveNote: require('./moveNote'),

View File

@@ -4,6 +4,7 @@ const resolveStorageData = require('./resolveStorageData')
const resolveStorageNotes = require('./resolveStorageNotes')
const consts = require('browser/lib/consts')
const path = require('path')
const fs = require('fs')
const CSON = require('@rokt33r/season')
/**
* @return {Object} all storages and notes
@@ -19,50 +20,64 @@ const CSON = require('@rokt33r/season')
* 2. legacy
* 3. empty directory
*/
function init () {
const fetchStorages = function () {
function init() {
const fetchStorages = function() {
let rawStorages
try {
rawStorages = JSON.parse(window.localStorage.getItem('storages'))
// Remove storages who's location is inaccesible.
rawStorages = rawStorages.filter(storage => fs.existsSync(storage.path))
if (!_.isArray(rawStorages)) throw new Error('Cached data is not valid.')
} catch (e) {
console.warn('Failed to parse cached data from localStorage', e)
rawStorages = []
window.localStorage.setItem('storages', JSON.stringify(rawStorages))
}
return Promise.all(rawStorages
.map(resolveStorageData))
return Promise.all(rawStorages.map(resolveStorageData))
}
const fetchNotes = function (storages) {
const fetchNotes = function(storages) {
const findNotesFromEachStorage = storages
.map((storage) => {
return resolveStorageNotes(storage)
.then((notes) => {
let unknownCount = 0
notes.forEach((note) => {
if (note && !storage.folders.some((folder) => note.folder === folder.key)) {
unknownCount++
storage.folders.push({
key: note.folder,
color: consts.FOLDER_COLORS[(unknownCount - 1) % 7],
name: 'Unknown ' + unknownCount
})
}
})
if (unknownCount > 0) {
CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['folders', 'version']))
.filter(storage => fs.existsSync(storage.path))
.map(storage => {
return resolveStorageNotes(storage).then(notes => {
let unknownCount = 0
notes.forEach(note => {
if (
note &&
!storage.folders.some(folder => note.folder === folder.key)
) {
unknownCount++
storage.folders.push({
key: note.folder,
color: consts.FOLDER_COLORS[(unknownCount - 1) % 7],
name: 'Unknown ' + unknownCount
})
}
return notes
})
if (unknownCount > 0) {
try {
CSON.writeFileSync(
path.join(storage.path, 'boostnote.json'),
_.pick(storage, ['folders', 'version'])
)
} catch (e) {
console.log(
'Error writting boostnote.json: ' + e + ' from init.js'
)
}
}
return notes
})
})
return Promise.all(findNotesFromEachStorage)
.then(function concatNoteGroup (noteGroups) {
return noteGroups.reduce(function (sum, group) {
.then(function concatNoteGroup(noteGroups) {
return noteGroups.reduce(function(sum, group) {
return sum.concat(group)
}, [])
})
.then(function returnData (notes) {
.then(function returnData(notes) {
return {
storages,
notes
@@ -71,12 +86,11 @@ function init () {
}
return Promise.resolve(fetchStorages())
.then((storages) => {
return storages
.filter((storage) => {
if (!_.isObject(storage)) return false
return true
})
.then(storages => {
return storages.filter(storage => {
if (!_.isObject(storage)) return false
return true
})
})
.then(fetchNotes)
}

View File

@@ -6,102 +6,111 @@ const CSON = require('@rokt33r/season')
const path = require('path')
const sander = require('sander')
function migrateFromV5Storage (storageKey, data) {
function migrateFromV5Storage(storageKey, data) {
let targetStorage
try {
const cachedStorageList = JSON.parse(localStorage.getItem('storages'))
if (!_.isArray(cachedStorageList)) throw new Error('Target storage doesn\'t exist.')
if (!_.isArray(cachedStorageList))
throw new Error("Target storage doesn't exist.")
targetStorage = _.find(cachedStorageList, {key: storageKey})
if (targetStorage == null) throw new Error('Target storage doesn\'t exist.')
targetStorage = _.find(cachedStorageList, { key: storageKey })
if (targetStorage == null) throw new Error("Target storage doesn't exist.")
} catch (e) {
return Promise.reject(e)
}
return resolveStorageData(targetStorage)
.then(function (storage) {
return importAll(storage, data)
})
return resolveStorageData(targetStorage).then(function(storage) {
return importAll(storage, data)
})
}
function importAll (storage, data) {
function importAll(storage, data) {
const oldArticles = data.articles
const notes = []
data.folders
.forEach(function (oldFolder) {
let folderKey = keygen()
while (storage.folders.some((folder) => folder.key === folderKey)) {
folderKey = keygen()
}
const newFolder = {
key: folderKey,
name: oldFolder.name,
color: consts.FOLDER_COLORS[Math.floor(Math.random() * 7) % 7]
}
data.folders.forEach(function(oldFolder) {
let folderKey = keygen()
while (storage.folders.some(folder => folder.key === folderKey)) {
folderKey = keygen()
}
const newFolder = {
key: folderKey,
name: oldFolder.name,
color: consts.FOLDER_COLORS[Math.floor(Math.random() * 7) % 7]
}
storage.folders.push(newFolder)
storage.folders.push(newFolder)
const articles = oldArticles.filter((article) => article.FolderKey === oldFolder.key)
articles.forEach((article) => {
let noteKey = keygen()
let isUnique = false
while (!isUnique) {
try {
sander.statSync(path.join(storage.path, 'notes', noteKey + '.cson'))
noteKey = keygen()
} catch (err) {
if (err.code === 'ENOENT') {
isUnique = true
} else {
console.error('Failed to read `notes` directory.')
throw err
}
const articles = oldArticles.filter(
article => article.FolderKey === oldFolder.key
)
articles.forEach(article => {
let noteKey = keygen()
let isUnique = false
while (!isUnique) {
try {
sander.statSync(path.join(storage.path, 'notes', noteKey + '.cson'))
noteKey = keygen()
} catch (err) {
if (err.code === 'ENOENT') {
isUnique = true
} else {
console.error('Failed to read `notes` directory.')
throw err
}
}
}
if (article.mode === 'markdown') {
const newNote = {
tags: article.tags,
createdAt: article.createdAt,
updatedAt: article.updatedAt,
folder: folderKey,
storage: storage.key,
type: 'MARKDOWN_NOTE',
isStarred: false,
title: article.title,
content: '# ' + article.title + '\n\n' + article.content,
key: noteKey,
linesHighlighted: article.linesHighlighted
}
notes.push(newNote)
} else {
const newNote = {
tags: article.tags,
createdAt: article.createdAt,
updatedAt: article.updatedAt,
folder: folderKey,
storage: storage.key,
type: 'SNIPPET_NOTE',
isStarred: false,
title: article.title,
description: article.title,
key: noteKey,
snippets: [{
if (article.mode === 'markdown') {
const newNote = {
tags: article.tags,
createdAt: article.createdAt,
updatedAt: article.updatedAt,
folder: folderKey,
storage: storage.key,
type: 'MARKDOWN_NOTE',
isStarred: false,
title: article.title,
content: '# ' + article.title + '\n\n' + article.content,
key: noteKey,
linesHighlighted: article.linesHighlighted
}
notes.push(newNote)
} else {
const newNote = {
tags: article.tags,
createdAt: article.createdAt,
updatedAt: article.updatedAt,
folder: folderKey,
storage: storage.key,
type: 'SNIPPET_NOTE',
isStarred: false,
title: article.title,
description: article.title,
key: noteKey,
snippets: [
{
name: article.mode,
mode: article.mode,
content: article.content,
linesHighlighted: article.linesHighlighted
}]
}
notes.push(newNote)
}
]
}
})
notes.push(newNote)
}
})
notes.forEach(function (note) {
CSON.writeFileSync(path.join(storage.path, 'notes', note.key + '.cson'), _.omit(note, ['storage', 'key']))
})
CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['version', 'folders']))
notes.forEach(function(note) {
CSON.writeFileSync(
path.join(storage.path, 'notes', note.key + '.cson'),
_.omit(note, ['storage', 'key'])
)
})
CSON.writeFileSync(
path.join(storage.path, 'boostnote.json'),
_.pick(storage, ['version', 'folders'])
)
return {
storage,

View File

@@ -4,86 +4,91 @@ const keygen = require('browser/lib/keygen')
const _ = require('lodash')
const CSON = require('@rokt33r/season')
function migrateFromV5Storage (storagePath) {
function migrateFromV5Storage(storagePath) {
var boostnoteJSONPath = path.join(storagePath, 'boostnote.json')
return Promise.resolve()
.then(function readBoostnoteJSON () {
.then(function readBoostnoteJSON() {
return sander.readFile(boostnoteJSONPath, {
encoding: 'utf-8'
})
})
.then(function verifyVersion (rawData) {
.then(function verifyVersion(rawData) {
var boostnoteJSONData = JSON.parse(rawData)
if (boostnoteJSONData.version === '1.0') throw new Error('Target storage seems to be transformed already.')
if (!_.isArray(boostnoteJSONData.folders)) throw new Error('the value of folders is not an array.')
if (boostnoteJSONData.version === '1.0')
throw new Error('Target storage seems to be transformed already.')
if (!_.isArray(boostnoteJSONData.folders))
throw new Error('the value of folders is not an array.')
return boostnoteJSONData
})
.then(function setVersion (boostnoteJSONData) {
.then(function setVersion(boostnoteJSONData) {
boostnoteJSONData.version = '1.0'
return sander.writeFile(boostnoteJSONPath, JSON.stringify(boostnoteJSONData))
return sander
.writeFile(boostnoteJSONPath, JSON.stringify(boostnoteJSONData))
.then(() => boostnoteJSONData)
})
.then(function fetchNotes (boostnoteJSONData) {
var fetchNotesFromEachFolder = boostnoteJSONData.folders
.map(function (folder) {
const folderDataJSONPath = path.join(storagePath, folder.key, 'data.json')
return sander
.readFile(folderDataJSONPath, {
encoding: 'utf-8'
.then(function fetchNotes(boostnoteJSONData) {
var fetchNotesFromEachFolder = boostnoteJSONData.folders.map(function(
folder
) {
const folderDataJSONPath = path.join(
storagePath,
folder.key,
'data.json'
)
return sander
.readFile(folderDataJSONPath, {
encoding: 'utf-8'
})
.then(function(rawData) {
var data = JSON.parse(rawData)
if (!_.isArray(data.notes))
throw new Error('value of notes is not an array.')
return data.notes.map(function setFolderToNote(note) {
note.folder = folder.key
return note
})
.then(function (rawData) {
var data = JSON.parse(rawData)
if (!_.isArray(data.notes)) throw new Error('value of notes is not an array.')
return data.notes
.map(function setFolderToNote (note) {
note.folder = folder.key
return note
})
})
.catch(function failedToReadDataJSON (err) {
console.warn('Failed to fetch notes from ', folderDataJSONPath, err)
return []
})
})
})
.catch(function failedToReadDataJSON(err) {
console.warn('Failed to fetch notes from ', folderDataJSONPath, err)
return []
})
})
return Promise.all(fetchNotesFromEachFolder)
.then(function flatten (folderNotes) {
return folderNotes
.reduce(function concatNotes (sum, notes) {
return sum.concat(notes)
}, [])
.then(function flatten(folderNotes) {
return folderNotes.reduce(function concatNotes(sum, notes) {
return sum.concat(notes)
}, [])
})
.then(function saveNotes (notes) {
notes.forEach(function renewKey (note) {
.then(function saveNotes(notes) {
notes.forEach(function renewKey(note) {
var newKey = keygen()
while (notes.some((_note) => _note.key === newKey)) {
while (notes.some(_note => _note.key === newKey)) {
newKey = keygen()
}
note.key = newKey
})
const noteDirPath = path.join(storagePath, 'notes')
notes
.map(function saveNote (note) {
CSON.writeFileSync(path.join(noteDirPath, note.key) + '.cson', note)
})
notes.map(function saveNote(note) {
CSON.writeFileSync(path.join(noteDirPath, note.key) + '.cson', note)
})
return true
})
.then(function deleteFolderDir (check) {
.then(function deleteFolderDir(check) {
if (check) {
boostnoteJSONData.folders.forEach((folder) => {
boostnoteJSONData.folders.forEach(folder => {
sander.rimrafSync(path.join(storagePath, folder.key))
})
}
return check
})
})
.catch(function handleError (err) {
.catch(function handleError(err) {
console.warn(err)
return false
})
}
module.exports = migrateFromV5Storage

View File

@@ -7,90 +7,104 @@ const sander = require('sander')
const { findStorage } = require('browser/lib/findStorage')
const attachmentManagement = require('./attachmentManagement')
function moveNote (storageKey, noteKey, newStorageKey, newFolderKey) {
function moveNote(storageKey, noteKey, newStorageKey, newFolderKey) {
let oldStorage, newStorage
try {
oldStorage = findStorage(storageKey)
newStorage = findStorage(newStorageKey)
if (newStorage == null) throw new Error('Target storage doesn\'t exist.')
if (newStorage == null) throw new Error("Target storage doesn't exist.")
} catch (e) {
return Promise.reject(e)
}
return resolveStorageData(oldStorage)
.then(function saveNote (_oldStorage) {
oldStorage = _oldStorage
let noteData
const notePath = path.join(oldStorage.path, 'notes', noteKey + '.cson')
try {
noteData = CSON.readFileSync(notePath)
} catch (err) {
console.warn('Failed to find note cson', err)
throw err
}
let newNoteKey
return Promise.resolve()
.then(function resolveNewStorage () {
if (storageKey === newStorageKey) {
newNoteKey = noteKey
return oldStorage
}
return resolveStorageData(newStorage)
.then(function findNewNoteKey (_newStorage) {
newStorage = _newStorage
newNoteKey = keygen(true)
let isUnique = false
while (!isUnique) {
try {
sander.statSync(path.join(newStorage.path, 'notes', newNoteKey + '.cson'))
newNoteKey = keygen(true)
} catch (err) {
if (err.code === 'ENOENT') {
isUnique = true
} else {
throw err
}
}
}
return newStorage
})
})
.then(function checkFolderExistsAndPrepareNoteData (newStorage) {
if (_.find(newStorage.folders, {key: newFolderKey}) == null) throw new Error('Target folder doesn\'t exist.')
noteData.folder = newFolderKey
noteData.key = newNoteKey
noteData.storage = newStorageKey
noteData.updatedAt = new Date()
noteData.oldContent = noteData.content
return noteData
})
.then(function moveAttachments (noteData) {
if (oldStorage.path === newStorage.path) {
return noteData
}
noteData.content = attachmentManagement.moveAttachments(oldStorage.path, newStorage.path, noteKey, newNoteKey, noteData.content)
return noteData
})
.then(function writeAndReturn (noteData) {
CSON.writeFileSync(path.join(newStorage.path, 'notes', noteData.key + '.cson'), _.omit(noteData, ['key', 'storage', 'oldContent']))
return noteData
})
.then(function deleteOldNote (data) {
if (storageKey !== newStorageKey) {
return resolveStorageData(oldStorage).then(function saveNote(_oldStorage) {
oldStorage = _oldStorage
let noteData
const notePath = path.join(oldStorage.path, 'notes', noteKey + '.cson')
try {
noteData = CSON.readFileSync(notePath)
} catch (err) {
console.warn('Failed to find note cson', err)
throw err
}
let newNoteKey
return Promise.resolve()
.then(function resolveNewStorage() {
if (storageKey === newStorageKey) {
newNoteKey = noteKey
return oldStorage
}
return resolveStorageData(newStorage).then(function findNewNoteKey(
_newStorage
) {
newStorage = _newStorage
newNoteKey = keygen(true)
let isUnique = false
while (!isUnique) {
try {
sander.unlinkSync(path.join(oldStorage.path, 'notes', noteKey + '.cson'))
sander.statSync(
path.join(newStorage.path, 'notes', newNoteKey + '.cson')
)
newNoteKey = keygen(true)
} catch (err) {
console.warn(err)
if (err.code === 'ENOENT') {
isUnique = true
} else {
throw err
}
}
}
return data
return newStorage
})
})
})
.then(function checkFolderExistsAndPrepareNoteData(newStorage) {
if (_.find(newStorage.folders, { key: newFolderKey }) == null)
throw new Error("Target folder doesn't exist.")
noteData.folder = newFolderKey
noteData.key = newNoteKey
noteData.storage = newStorageKey
noteData.updatedAt = new Date()
noteData.oldContent = noteData.content
return noteData
})
.then(function moveAttachments(noteData) {
if (oldStorage.path === newStorage.path) {
return noteData
}
noteData.content = attachmentManagement.moveAttachments(
oldStorage.path,
newStorage.path,
noteKey,
newNoteKey,
noteData.content
)
return noteData
})
.then(function writeAndReturn(noteData) {
CSON.writeFileSync(
path.join(newStorage.path, 'notes', noteData.key + '.cson'),
_.omit(noteData, ['key', 'storage', 'oldContent'])
)
return noteData
})
.then(function deleteOldNote(data) {
if (storageKey !== newStorageKey) {
try {
sander.unlinkSync(
path.join(oldStorage.path, 'notes', noteKey + '.cson')
)
} catch (err) {
console.warn(err)
}
}
return data
})
})
}
module.exports = moveNote

View File

@@ -4,7 +4,7 @@ const _ = require('lodash')
* @param {String} key
* @return {key}
*/
function removeStorage (key) {
function removeStorage(key) {
let rawStorages
try {
@@ -15,10 +15,9 @@ function removeStorage (key) {
rawStorages = []
}
rawStorages = rawStorages
.filter(function excludeTargetStorage (rawStorage) {
return rawStorage.key !== key
})
rawStorages = rawStorages.filter(function excludeTargetStorage(rawStorage) {
return rawStorage.key !== key
})
localStorage.setItem('storages', JSON.stringify(rawStorages))

View File

@@ -6,8 +6,9 @@ const resolveStorageData = require('./resolveStorageData')
* @param {String} name
* @return {Object} Storage meta data
*/
function renameStorage (key, name) {
if (!_.isString(name)) return Promise.reject(new Error('Name must be a string.'))
function renameStorage(key, name) {
if (!_.isString(name))
return Promise.reject(new Error('Name must be a string.'))
let cachedStorageList
try {
@@ -17,7 +18,7 @@ function renameStorage (key, name) {
console.error(err)
return Promise.reject(err)
}
const targetStorage = _.find(cachedStorageList, {key: key})
const targetStorage = _.find(cachedStorageList, { key: key })
if (targetStorage == null) return Promise.reject('Storage')
targetStorage.name = name

View File

@@ -17,7 +17,7 @@ const { findStorage } = require('browser/lib/findStorage')
* }
* ```
*/
function reorderFolder (storageKey, oldIndex, newIndex) {
function reorderFolder(storageKey, oldIndex, newIndex) {
let targetStorage
try {
if (!_.isNumber(oldIndex)) throw new Error('oldIndex must be a number.')
@@ -28,15 +28,19 @@ function reorderFolder (storageKey, oldIndex, newIndex) {
return Promise.reject(e)
}
return resolveStorageData(targetStorage)
.then(function reorderFolder (storage) {
storage.folders = _.move(storage.folders, oldIndex, newIndex)
CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['folders', 'version']))
return resolveStorageData(targetStorage).then(function reorderFolder(
storage
) {
storage.folders = _.move(storage.folders, oldIndex, newIndex)
CSON.writeFileSync(
path.join(storage.path, 'boostnote.json'),
_.pick(storage, ['folders', 'version'])
)
return {
storage
}
})
return {
storage
}
})
}
module.exports = reorderFolder

View File

@@ -3,7 +3,7 @@ const path = require('path')
const CSON = require('@rokt33r/season')
const migrateFromV6Storage = require('./migrateFromV6Storage')
function resolveStorageData (storageCache) {
function resolveStorageData(storageCache) {
const storage = {
key: storageCache.key,
name: storageCache.name,
@@ -15,13 +15,14 @@ function resolveStorageData (storageCache) {
const boostnoteJSONPath = path.join(storageCache.path, 'boostnote.json')
try {
const jsonData = CSON.readFileSync(boostnoteJSONPath)
if (!_.isArray(jsonData.folders)) throw new Error('folders should be an array.')
if (!_.isArray(jsonData.folders))
throw new Error('folders should be an array.')
storage.folders = jsonData.folders
storage.version = jsonData.version
} catch (err) {
if (err.code === 'ENOENT') {
console.warn('boostnote.json file doesn\'t exist the given path')
CSON.writeFileSync(boostnoteJSONPath, {folders: [], version: '1.0'})
console.warn("boostnote.json file doesn't exist the given path")
CSON.writeFileSync(boostnoteJSONPath, { folders: [], version: '1.0' })
} else {
console.error(err)
}
@@ -34,8 +35,7 @@ function resolveStorageData (storageCache) {
return Promise.resolve(storage)
}
return migrateFromV6Storage(storage.path)
.then(() => storage)
return migrateFromV6Storage(storage.path).then(() => storage)
}
module.exports = resolveStorageData

View File

@@ -2,14 +2,14 @@ const sander = require('sander')
const path = require('path')
const CSON = require('@rokt33r/season')
function resolveStorageNotes (storage) {
function resolveStorageNotes(storage) {
const notesDirPath = path.join(storage.path, 'notes')
let notePathList
try {
notePathList = sander.readdirSync(notesDirPath)
} catch (err) {
if (err.code === 'ENOENT') {
console.error(notesDirPath, ' doesn\'t exist.')
console.error(notesDirPath, " doesn't exist.")
sander.mkdirSync(notesDirPath)
} else {
console.warn('Failed to find note dir', notesDirPath, err)
@@ -17,10 +17,10 @@ function resolveStorageNotes (storage) {
notePathList = []
}
const notes = notePathList
.filter(function filterOnlyCSONFile (notePath) {
.filter(function filterOnlyCSONFile(notePath) {
return /\.cson$/.test(notePath)
})
.map(function parseCSONFile (notePath) {
.map(function parseCSONFile(notePath) {
try {
const data = CSON.readFileSync(path.join(notesDirPath, notePath))
data.key = path.basename(notePath, '.cson')
@@ -30,7 +30,7 @@ function resolveStorageNotes (storage) {
console.error(`error on note path: ${notePath}, error: ${err}`)
}
})
.filter(function filterOnlyNoteObject (noteObj) {
.filter(function filterOnlyNoteObject(noteObj) {
return typeof noteObj === 'object'
})

View File

@@ -6,7 +6,7 @@ const resolveStorageData = require('./resolveStorageData')
* @param {Boolean} isOpen
* @return {Object} Storage meta data
*/
function toggleStorage (key, isOpen) {
function toggleStorage(key, isOpen) {
let cachedStorageList
try {
cachedStorageList = JSON.parse(localStorage.getItem('storages'))
@@ -15,7 +15,7 @@ function toggleStorage (key, isOpen) {
console.error(err)
return Promise.reject(err)
}
const targetStorage = _.find(cachedStorageList, {key: key})
const targetStorage = _.find(cachedStorageList, { key: key })
if (targetStorage == null) return Promise.reject('Storage')
targetStorage.isOpen = isOpen

View File

@@ -22,7 +22,7 @@ const { findStorage } = require('browser/lib/findStorage')
* }
* ```
*/
function updateFolder (storageKey, folderKey, input) {
function updateFolder(storageKey, folderKey, input) {
let targetStorage
try {
if (input == null) throw new Error('No input found.')
@@ -34,19 +34,21 @@ function updateFolder (storageKey, folderKey, input) {
return Promise.reject(e)
}
return resolveStorageData(targetStorage)
.then(function updateFolder (storage) {
const targetFolder = _.find(storage.folders, {key: folderKey})
if (targetFolder == null) throw new Error('Target folder doesn\'t exist.')
targetFolder.name = input.name
targetFolder.color = input.color
return resolveStorageData(targetStorage).then(function updateFolder(storage) {
const targetFolder = _.find(storage.folders, { key: folderKey })
if (targetFolder == null) throw new Error("Target folder doesn't exist.")
targetFolder.name = input.name
targetFolder.color = input.color
CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['folders', 'version']))
CSON.writeFileSync(
path.join(storage.path, 'boostnote.json'),
_.pick(storage, ['folders', 'version'])
)
return {
storage
}
})
return {
storage
}
})
}
module.exports = updateFolder

View File

@@ -4,13 +4,14 @@ const path = require('path')
const CSON = require('@rokt33r/season')
const { findStorage } = require('browser/lib/findStorage')
function validateInput (input) {
function validateInput(input) {
const validatedInput = {}
if (input.tags != null) {
if (!_.isArray(input.tags)) validatedInput.tags = []
validatedInput.tags = input.tags
.filter((tag) => _.isString(tag) && tag.trim().length > 0)
validatedInput.tags = input.tags.filter(
tag => _.isString(tag) && tag.trim().length > 0
)
}
if (input.title != null) {
@@ -40,7 +41,8 @@ function validateInput (input) {
if (!_.isString(input.content)) validatedInput.content = ''
else validatedInput.content = input.content
if (!_.isArray(input.linesHighlighted)) validatedInput.linesHighlighted = []
if (!_.isArray(input.linesHighlighted))
validatedInput.linesHighlighted = []
else validatedInput.linesHighlighted = input.linesHighlighted
}
return validatedInput
@@ -51,30 +53,33 @@ function validateInput (input) {
}
if (input.snippets != null) {
if (!_.isArray(input.snippets)) {
validatedInput.snippets = [{
name: '',
mode: 'text',
content: '',
linesHighlighted: []
}]
validatedInput.snippets = [
{
name: '',
mode: 'text',
content: '',
linesHighlighted: []
}
]
} else {
validatedInput.snippets = input.snippets
}
validatedInput.snippets
.filter((snippet) => {
if (!_.isString(snippet.name)) return false
if (!_.isString(snippet.mode)) return false
if (!_.isString(snippet.content)) return false
return true
})
validatedInput.snippets.filter(snippet => {
if (!_.isString(snippet.name)) return false
if (!_.isString(snippet.mode)) return false
if (!_.isString(snippet.content)) return false
return true
})
}
return validatedInput
default:
throw new Error('Invalid type: only MARKDOWN_NOTE and SNIPPET_NOTE are available.')
throw new Error(
'Invalid type: only MARKDOWN_NOTE and SNIPPET_NOTE are available.'
)
}
}
function updateNote (storageKey, noteKey, input) {
function updateNote(storageKey, noteKey, input) {
let targetStorage
try {
if (input == null) throw new Error('No input found.')
@@ -85,55 +90,61 @@ function updateNote (storageKey, noteKey, input) {
return Promise.reject(e)
}
return resolveStorageData(targetStorage)
.then(function saveNote (storage) {
let noteData
const notePath = path.join(storage.path, 'notes', noteKey + '.cson')
try {
noteData = CSON.readFileSync(notePath)
} catch (err) {
console.warn('Failed to find note cson', err)
noteData = input.type === 'SNIPPET_NOTE'
return resolveStorageData(targetStorage).then(function saveNote(storage) {
let noteData
const notePath = path.join(storage.path, 'notes', noteKey + '.cson')
try {
noteData = CSON.readFileSync(notePath)
} catch (err) {
console.warn('Failed to find note cson', err)
noteData =
input.type === 'SNIPPET_NOTE'
? {
type: 'SNIPPET_NOTE',
description: [],
snippets: [{
name: '',
mode: 'text',
type: 'SNIPPET_NOTE',
description: [],
snippets: [
{
name: '',
mode: 'text',
content: '',
linesHighlighted: []
}
]
}
: {
type: 'MARKDOWN_NOTE',
content: '',
linesHighlighted: []
}]
}
: {
type: 'MARKDOWN_NOTE',
content: '',
linesHighlighted: []
}
noteData.title = ''
if (storage.folders.length === 0) throw new Error('Failed to restore note: No folder exists.')
noteData.folder = storage.folders[0].key
noteData.createdAt = new Date()
noteData.updatedAt = new Date()
noteData.isStarred = false
noteData.isTrashed = false
noteData.tags = []
noteData.isPinned = false
}
}
noteData.title = ''
if (storage.folders.length === 0)
throw new Error('Failed to restore note: No folder exists.')
noteData.folder = storage.folders[0].key
noteData.createdAt = new Date()
noteData.updatedAt = new Date()
noteData.isStarred = false
noteData.isTrashed = false
noteData.tags = []
noteData.isPinned = false
}
if (noteData.type === 'SNIPPET_NOTE') {
noteData.title
}
if (noteData.type === 'SNIPPET_NOTE') {
noteData.title
}
Object.assign(noteData, input, {
key: noteKey,
updatedAt: new Date(),
storage: storageKey
})
CSON.writeFileSync(path.join(storage.path, 'notes', noteKey + '.cson'), _.omit(noteData, ['key', 'storage']))
return noteData
Object.assign(noteData, input, {
key: noteKey,
updatedAt: new Date(),
storage: storageKey
})
CSON.writeFileSync(
path.join(storage.path, 'notes', noteKey + '.cson'),
_.omit(noteData, ['key', 'storage'])
)
return noteData
})
}
module.exports = updateNote

View File

@@ -1,9 +1,11 @@
import fs from 'fs'
import consts from 'browser/lib/consts'
function updateSnippet (snippet, snippetFile) {
function updateSnippet(snippet, snippetFile) {
return new Promise((resolve, reject) => {
const snippets = JSON.parse(fs.readFileSync(snippetFile || consts.SNIPPET_FILE, 'utf-8'))
const snippets = JSON.parse(
fs.readFileSync(snippetFile || consts.SNIPPET_FILE, 'utf-8')
)
for (let i = 0; i < snippets.length; i++) {
const currentSnippet = snippets[i]
@@ -21,11 +23,15 @@ function updateSnippet (snippet, snippetFile) {
currentSnippet.name = snippet.name
currentSnippet.prefix = snippet.prefix
currentSnippet.content = snippet.content
currentSnippet.linesHighlighted = (snippet.linesHighlighted)
fs.writeFile(snippetFile || consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => {
if (err) reject(err)
resolve(snippets)
})
currentSnippet.linesHighlighted = snippet.linesHighlighted
fs.writeFile(
snippetFile || consts.SNIPPET_FILE,
JSON.stringify(snippets, null, 4),
err => {
if (err) reject(err)
resolve(snippets)
}
)
}
}
}