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

Merge branch 'master' into Moving_Note_With_Attachment

This commit is contained in:
Junyoung Choi (Sai)
2018-05-17 01:28:47 +09:00
committed by GitHub
15 changed files with 95 additions and 7 deletions

View File

@@ -283,6 +283,7 @@ class MarkdownEditor extends React.Component {
indentSize={editorIndentSize} indentSize={editorIndentSize}
scrollPastEnd={config.preview.scrollPastEnd} scrollPastEnd={config.preview.scrollPastEnd}
smartQuotes={config.preview.smartQuotes} smartQuotes={config.preview.smartQuotes}
breaks={config.preview.breaks}
sanitize={config.preview.sanitize} sanitize={config.preview.sanitize}
ref='preview' ref='preview'
onContextMenu={(e) => this.handleContextMenu(e)} onContextMenu={(e) => this.handleContextMenu(e)}

View File

@@ -145,10 +145,11 @@ export default class MarkdownPreview extends React.Component {
} }
initMarkdown () { initMarkdown () {
const { smartQuotes, sanitize } = this.props const { smartQuotes, sanitize, breaks } = this.props
this.markdown = new Markdown({ this.markdown = new Markdown({
typographer: smartQuotes, typographer: smartQuotes,
sanitize sanitize,
breaks
}) })
} }
@@ -340,7 +341,9 @@ export default class MarkdownPreview extends React.Component {
componentDidUpdate (prevProps) { componentDidUpdate (prevProps) {
if (prevProps.value !== this.props.value) this.rewriteIframe() if (prevProps.value !== this.props.value) this.rewriteIframe()
if (prevProps.smartQuotes !== this.props.smartQuotes || prevProps.sanitize !== this.props.sanitize) { if (prevProps.smartQuotes !== this.props.smartQuotes ||
prevProps.sanitize !== this.props.sanitize ||
prevProps.breaks !== this.props.breaks) {
this.initMarkdown() this.initMarkdown()
this.rewriteIframe() this.rewriteIframe()
} }
@@ -599,5 +602,6 @@ MarkdownPreview.propTypes = {
value: PropTypes.string, value: PropTypes.string,
showCopyNotification: PropTypes.bool, showCopyNotification: PropTypes.bool,
storagePath: PropTypes.string, storagePath: PropTypes.string,
smartQuotes: PropTypes.bool smartQuotes: PropTypes.bool,
breaks: PropTypes.bool
} }

View File

@@ -131,6 +131,7 @@ class MarkdownSplitEditor extends React.Component {
lineNumber={config.preview.lineNumber} lineNumber={config.preview.lineNumber}
scrollPastEnd={config.preview.scrollPastEnd} scrollPastEnd={config.preview.scrollPastEnd}
smartQuotes={config.preview.smartQuotes} smartQuotes={config.preview.smartQuotes}
breaks={config.preview.breaks}
sanitize={config.preview.sanitize} sanitize={config.preview.sanitize}
ref='preview' ref='preview'
tabInde='0' tabInde='0'

View File

@@ -25,7 +25,7 @@ class Markdown {
linkify: true, linkify: true,
html: true, html: true,
xhtmlOut: true, xhtmlOut: true,
breaks: true, breaks: config.preview.breaks,
highlight: function (str, lang) { highlight: function (str, lang) {
const delimiter = ':' const delimiter = ':'
const langInfo = lang.split(delimiter) const langInfo = lang.split(delimiter)

View File

@@ -56,6 +56,7 @@ export const DEFAULT_CONFIG = {
plantUMLServerAddress: 'http://www.plantuml.com/plantuml', plantUMLServerAddress: 'http://www.plantuml.com/plantuml',
scrollPastEnd: false, scrollPastEnd: false,
smartQuotes: true, smartQuotes: true,
breaks: true,
sanitize: 'STRICT' // 'STRICT', 'ALLOW_STYLES', 'NONE' sanitize: 'STRICT' // 'STRICT', 'ALLOW_STYLES', 'NONE'
}, },
blog: { blog: {

View File

@@ -5,6 +5,7 @@ const findStorage = require('browser/lib/findStorage')
const mdurl = require('mdurl') const mdurl = require('mdurl')
const fse = require('fs-extra') const fse = require('fs-extra')
const escapeStringRegexp = require('escape-string-regexp') const escapeStringRegexp = require('escape-string-regexp')
const sander = require('sander')
const STORAGE_FOLDER_PLACEHOLDER = ':storage' const STORAGE_FOLDER_PLACEHOLDER = ':storage'
const DESTINATION_FOLDER = 'attachments' const DESTINATION_FOLDER = 'attachments'
@@ -213,6 +214,17 @@ function removeStorageAndNoteReferences (input, noteKey) {
return input.replace(new RegExp(mdurl.encode(path.sep), 'g'), path.sep).replace(new RegExp(STORAGE_FOLDER_PLACEHOLDER + escapeStringRegexp(path.sep) + noteKey, 'g'), DESTINATION_FOLDER) return input.replace(new RegExp(mdurl.encode(path.sep), 'g'), path.sep).replace(new RegExp(STORAGE_FOLDER_PLACEHOLDER + escapeStringRegexp(path.sep) + noteKey, 'g'), DESTINATION_FOLDER)
} }
/**
* @description Deletes the attachment folder specified by the given storageKey and noteKey
* @param storageKey Key of the storage of the note to be deleted
* @param noteKey Key of the note to be deleted
*/
function deleteAttachmentFolder (storageKey, noteKey) {
const storagePath = findStorage.findStorage(storageKey)
const noteAttachmentPath = path.join(storagePath.path, DESTINATION_FOLDER, noteKey)
sander.rimrafSync(noteAttachmentPath)
}
/** /**
* @description Deletes all attachments stored in the attachment folder of the give not that are not referenced in the markdownContent * @description Deletes all attachments stored in the attachment folder of the give not that are not referenced in the markdownContent
* @param markdownContent Content of the note. All unreferenced notes will be deleted * @param markdownContent Content of the note. All unreferenced notes will be deleted
@@ -265,6 +277,7 @@ module.exports = {
getAttachmentsInContent, getAttachmentsInContent,
getAbsolutePathsOfAttachmentsInContent, getAbsolutePathsOfAttachmentsInContent,
removeStorageAndNoteReferences, removeStorageAndNoteReferences,
deleteAttachmentFolder,
deleteAttachmentsNotPresentInNote, deleteAttachmentsNotPresentInNote,
moveAttachments, moveAttachments,
STORAGE_FOLDER_PLACEHOLDER, STORAGE_FOLDER_PLACEHOLDER,

View File

@@ -1,6 +1,7 @@
const resolveStorageData = require('./resolveStorageData') const resolveStorageData = require('./resolveStorageData')
const path = require('path') const path = require('path')
const sander = require('sander') const sander = require('sander')
const attachmentManagement = require('./attachmentManagement')
const { findStorage } = require('browser/lib/findStorage') const { findStorage } = require('browser/lib/findStorage')
function deleteNote (storageKey, noteKey) { function deleteNote (storageKey, noteKey) {
@@ -25,6 +26,10 @@ function deleteNote (storageKey, noteKey) {
storageKey storageKey
} }
}) })
.then(function deleteAttachments (storageInfo) {
attachmentManagement.deleteAttachmentFolder(storageInfo.storageKey, storageInfo.noteKey)
return storageInfo
})
} }
module.exports = deleteNote module.exports = deleteNote

View File

@@ -97,6 +97,7 @@ class UiTab extends React.Component {
plantUMLServerAddress: this.refs.previewPlantUMLServerAddress.value, plantUMLServerAddress: this.refs.previewPlantUMLServerAddress.value,
scrollPastEnd: this.refs.previewScrollPastEnd.checked, scrollPastEnd: this.refs.previewScrollPastEnd.checked,
smartQuotes: this.refs.previewSmartQuotes.checked, smartQuotes: this.refs.previewSmartQuotes.checked,
breaks: this.refs.previewBreaks.checked,
sanitize: this.refs.previewSanitize.value sanitize: this.refs.previewSanitize.value
} }
} }
@@ -476,6 +477,16 @@ class UiTab extends React.Component {
Enable smart quotes Enable smart quotes
</label> </label>
</div> </div>
<div styleName='group-checkBoxSection'>
<label>
<input onChange={(e) => this.handleUIChange(e)}
checked={this.state.config.preview.breaks}
ref='previewBreaks'
type='checkbox'
/>&nbsp;
Render newlines in Markdown paragraphs as &lt;br&gt;
</label>
</div>
<div styleName='group-section'> <div styleName='group-section'>
<div styleName='group-section-label'> <div styleName='group-section-label'>

View File

@@ -53,7 +53,7 @@
"@rokt33r/season": "^5.3.0", "@rokt33r/season": "^5.3.0",
"aws-sdk": "^2.48.0", "aws-sdk": "^2.48.0",
"aws-sdk-mobile-analytics": "^0.9.2", "aws-sdk-mobile-analytics": "^0.9.2",
"codemirror": "^5.19.0", "codemirror": "^5.37.0",
"codemirror-mode-elixir": "^1.1.1", "codemirror-mode-elixir": "^1.1.1",
"electron-config": "^0.2.1", "electron-config": "^0.2.1",
"electron-gh-releases": "^2.0.2", "electron-gh-releases": "^2.0.2",

View File

@@ -8,6 +8,7 @@ jest.mock('unique-slug')
const uniqueSlug = require('unique-slug') const uniqueSlug = require('unique-slug')
const mdurl = require('mdurl') const mdurl = require('mdurl')
const fse = require('fs-extra') const fse = require('fs-extra')
const sander = require('sander')
const systemUnderTest = require('browser/main/lib/dataApi/attachmentManagement') const systemUnderTest = require('browser/main/lib/dataApi/attachmentManagement')
@@ -262,6 +263,19 @@ it('should remove the all ":storage" and noteKey references', function () {
expect(actual).toEqual(expectedOutput) expect(actual).toEqual(expectedOutput)
}) })
it('should delete the correct attachment folder if a note is deleted', function () {
const dummyStorage = {path: 'dummyStoragePath'}
const storageKey = 'storageKey'
const noteKey = 'noteKey'
findStorage.findStorage = jest.fn(() => dummyStorage)
sander.rimrafSync = jest.fn()
const expectedPathToBeDeleted = path.join(dummyStorage.path, systemUnderTest.DESTINATION_FOLDER, noteKey)
systemUnderTest.deleteAttachmentFolder(storageKey, noteKey)
expect(findStorage.findStorage).toHaveBeenCalledWith(storageKey)
expect(sander.rimrafSync).toHaveBeenCalledWith(expectedPathToBeDeleted)
})
it('should test that deleteAttachmentsNotPresentInNote deletes all unreferenced attachments ', function () { it('should test that deleteAttachmentsNotPresentInNote deletes all unreferenced attachments ', function () {
const dummyStorage = {path: 'dummyStoragePath'} const dummyStorage = {path: 'dummyStoragePath'}
const noteKey = 'noteKey' const noteKey = 'noteKey'

View File

@@ -14,6 +14,8 @@ const sander = require('sander')
const os = require('os') const os = require('os')
const CSON = require('@rokt33r/season') const CSON = require('@rokt33r/season')
const faker = require('faker') const faker = require('faker')
const fs = require('fs')
const attachmentManagement = require('browser/main/lib/dataApi/attachmentManagement')
const storagePath = path.join(os.tmpdir(), 'test/delete-note') const storagePath = path.join(os.tmpdir(), 'test/delete-note')
@@ -42,6 +44,11 @@ test.serial('Delete a note', (t) => {
return Promise.resolve() return Promise.resolve()
.then(function doTest () { .then(function doTest () {
return createNote(storageKey, input1) return createNote(storageKey, input1)
.then(function createAttachmentFolder (data) {
fs.mkdirSync(path.join(storagePath, attachmentManagement.DESTINATION_FOLDER))
fs.mkdirSync(path.join(storagePath, attachmentManagement.DESTINATION_FOLDER, data.key))
return data
})
.then(function (data) { .then(function (data) {
return deleteNote(storageKey, data.key) return deleteNote(storageKey, data.key)
}) })
@@ -52,8 +59,13 @@ test.serial('Delete a note', (t) => {
t.fail('note cson must be deleted.') t.fail('note cson must be deleted.')
} catch (err) { } catch (err) {
t.is(err.code, 'ENOENT') t.is(err.code, 'ENOENT')
return data
} }
}) })
.then(function assertAttachmentFolderDeleted (data) {
const attachmentFolderPath = path.join(storagePath, attachmentManagement.DESTINATION_FOLDER, data.noteKey)
t.is(fs.existsSync(attachmentFolderPath), false)
})
}) })
test.after(function after () { test.after(function after () {

View File

@@ -48,10 +48,13 @@ const checkboxes = `
const smartQuotes = 'This is a "QUOTE".' const smartQuotes = 'This is a "QUOTE".'
const breaks = 'This is the first line.\nThis is the second line.'
export default { export default {
basic, basic,
codeblock, codeblock,
katex, katex,
checkboxes, checkboxes,
smartQuotes smartQuotes,
breaks
} }

View File

@@ -34,3 +34,12 @@ test('Markdown.render() should text with quotes correctly', t => {
const renderedNonSmartQuotes = newmd.render(markdownFixtures.smartQuotes) const renderedNonSmartQuotes = newmd.render(markdownFixtures.smartQuotes)
t.snapshot(renderedNonSmartQuotes) t.snapshot(renderedNonSmartQuotes)
}) })
test('Markdown.render() should render line breaks correctly', t => {
const renderedBreaks = md.render(markdownFixtures.breaks)
t.snapshot(renderedBreaks)
const newmd = new Markdown({ breaks: false })
const renderedNonBreaks = newmd.render(markdownFixtures.breaks)
t.snapshot(renderedNonBreaks)
})

View File

@@ -4,6 +4,20 @@ The actual snapshot is saved in `markdown-test.js.snap`.
Generated by [AVA](https://ava.li). Generated by [AVA](https://ava.li).
## Markdown.render() should render line breaks correctly
> Snapshot 1
`<p data-line="0">This is the first line.<br />␊
This is the second line.</p>␊
`
> Snapshot 2
`<p data-line="0">This is the first line.␊
This is the second line.</p>␊
`
## Markdown.render() should renders KaTeX correctly ## Markdown.render() should renders KaTeX correctly
> Snapshot 1 > Snapshot 1