1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 17:56:25 +00:00

Merge remote-tracking branch 'upstream/master' into html-to-md

This commit is contained in:
AWolf81
2019-07-28 15:49:16 +02:00
71 changed files with 424 additions and 163 deletions

View File

@@ -11,7 +11,7 @@ const FullscreenButton = ({
const hotkey = (OSX ? i18n.__('Command(⌘)') : i18n.__('Ctrl(^)')) + '+B'
return (
<button styleName='control-fullScreenButton' title={i18n.__('Fullscreen')} onMouseDown={(e) => onClick(e)}>
<img styleName='iconInfo' src='../resources/icon/icon-full.svg' />
<img src='../resources/icon/icon-full.svg' />
<span lang={i18n.locale} styleName='tooltip'>{i18n.__('Fullscreen')}({hotkey})</span>
</button>
)

View File

@@ -60,7 +60,7 @@ class InfoPanel extends React.Component {
</div>
<div>
<input styleName='infoPanel-noteLink' ref='noteLink' value={noteLink} onClick={(e) => { e.target.select() }} />
<input styleName='infoPanel-noteLink' ref='noteLink' defaultValue={noteLink} onClick={(e) => { e.target.select() }} />
<button onClick={() => this.copyNoteLink()} styleName='infoPanel-copyButton'>
<i className='fa fa-clipboard' />
</button>

View File

@@ -311,7 +311,7 @@ class MarkdownNoteDetail extends React.Component {
}
getToggleLockButton () {
return this.state.isLocked ? '../resources/icon/icon-previewoff-on.svg' : '../resources/icon/icon-previewoff-off.svg'
return this.state.isLocked ? '../resources/icon/icon-lock.svg' : '../resources/icon/icon-unlock.svg'
}
handleDeleteKeyDown (e) {
@@ -450,7 +450,7 @@ class MarkdownNoteDetail extends React.Component {
const detailTopBar = <div styleName='info'>
<div styleName='info-left'>
<div styleName='info-left-top'>
<div>
<FolderSelect styleName='info-left-top-folderSelect'
value={this.state.note.storage + '-' + this.state.note.folder}
ref='folder'
@@ -485,7 +485,7 @@ class MarkdownNoteDetail extends React.Component {
onFocus={(e) => this.handleFocus(e)}
onMouseDown={(e) => this.handleLockButtonMouseDown(e)}
>
<img styleName='iconInfo' src={imgSrc} />
<img src={imgSrc} />
{this.state.isLocked ? <span styleName='tooltip'>Unlock</span> : <span styleName='tooltip'>Lock</span>}
</button>

View File

@@ -10,7 +10,7 @@ const PermanentDeleteButton = ({
<button styleName='control-trashButton--in-trash'
onClick={(e) => onClick(e)}
>
<img styleName='iconInfo' src='../resources/icon/icon-trash.svg' />
<img src='../resources/icon/icon-trash.svg' />
<span styleName='tooltip'>{i18n.__('Permanent Delete')}</span>
</button>
)

View File

@@ -518,6 +518,19 @@ class SnippetNoteDetail extends React.Component {
])
}
handleWrapLineButtonClick (e) {
context.popup([
{
label: 'on',
click: (e) => this.handleWrapLineItemClick(e, true)
},
{
label: 'off',
click: (e) => this.handleWrapLineItemClick(e, false)
}
])
}
handleIndentSizeItemClick (e, indentSize) {
const { config, dispatch } = this.props
const editor = Object.assign({}, config.editor, {
@@ -550,6 +563,22 @@ class SnippetNoteDetail extends React.Component {
})
}
handleWrapLineItemClick (e, lineWrapping) {
const { config, dispatch } = this.props
const editor = Object.assign({}, config.editor, {
lineWrapping
})
ConfigManager.set({
editor
})
dispatch({
type: 'SET_CONFIG',
config: {
editor
}
})
}
focus () {
this.refs.description.focus()
}
@@ -720,6 +749,7 @@ class SnippetNoteDetail extends React.Component {
mode={snippet.mode || (autoDetect ? null : config.editor.snippetDefaultLanguage)}
value={snippet.content}
linesHighlighted={snippet.linesHighlighted}
lineWrapping={config.editor.lineWrapping}
theme={config.editor.theme}
fontFamily={config.editor.fontFamily}
fontSize={editorFontSize}
@@ -778,7 +808,7 @@ class SnippetNoteDetail extends React.Component {
const detailTopBar = <div styleName='info'>
<div styleName='info-left'>
<div styleName='info-left-top'>
<div>
<FolderSelect styleName='info-left-top-folderSelect'
value={this.state.note.storage + '-' + this.state.note.folder}
ref='folder'
@@ -899,6 +929,12 @@ class SnippetNoteDetail extends React.Component {
size: {config.editor.indentSize}&nbsp;
<i className='fa fa-caret-down' />
</button>
<button
onClick={(e) => this.handleWrapLineButtonClick(e)}
>
Wrap Line: {config.editor.lineWrapping ? 'on' : 'off'}&nbsp;
<i className='fa fa-caret-down' />
</button>
</div>
<StatusBar

View File

@@ -8,11 +8,11 @@ const ToggleModeButton = ({
onClick, editorType
}) => (
<div styleName='control-toggleModeButton'>
<div styleName={editorType === 'SPLIT' ? 'active' : 'non-active'} onClick={() => onClick('SPLIT')}>
<img styleName='item-star' src={editorType === 'EDITOR_PREVIEW' ? '../resources/icon/icon-mode-markdown-off-active.svg' : ''} />
<div styleName={editorType === 'SPLIT' ? 'active' : undefined} onClick={() => onClick('SPLIT')}>
<img src={editorType === 'EDITOR_PREVIEW' ? '../resources/icon/icon-mode-markdown-off-active.svg' : ''} />
</div>
<div styleName={editorType === 'EDITOR_PREVIEW' ? 'active' : 'non-active'} onClick={() => onClick('EDITOR_PREVIEW')}>
<img styleName='item-star' src={editorType === 'EDITOR_PREVIEW' ? '' : '../resources/icon/icon-mode-split-on-active.svg'} />
<div styleName={editorType === 'EDITOR_PREVIEW' ? 'active' : undefined} onClick={() => onClick('EDITOR_PREVIEW')}>
<img src={editorType === 'EDITOR_PREVIEW' ? '' : '../resources/icon/icon-mode-split-on-active.svg'} />
</div>
<span lang={i18n.locale} styleName='tooltip'>{i18n.__('Toggle Mode')}</span>
</div>
@@ -20,7 +20,7 @@ const ToggleModeButton = ({
ToggleModeButton.propTypes = {
onClick: PropTypes.func.isRequired,
editorType: PropTypes.string.Required
editorType: PropTypes.string.isRequired
}
export default CSSModules(ToggleModeButton, styles)

View File

@@ -10,7 +10,7 @@ const TrashButton = ({
<button styleName='control-trashButton'
onClick={(e) => onClick(e)}
>
<img styleName='iconInfo' src='../resources/icon/icon-trash.svg' />
<img src='../resources/icon/icon-trash.svg' />
<span lang={i18n.locale} styleName='tooltip'>{i18n.__('Trash')}</span>
</button>
)

View File

@@ -1,8 +1,8 @@
/* eslint-disable no-undef */
if (process.env.NODE_ENV === 'production') {
// eslint-disable-next-line global-require
module.exports = require('./index.prod').default
} else {
if (process.env.NODE_ENV === 'development') {
// eslint-disable-next-line global-require
module.exports = require('./index.dev').default
} else {
// eslint-disable-next-line global-require
module.exports = require('./index.prod').default
}

View File

@@ -90,7 +90,7 @@ class NewNoteButton extends React.Component {
<div styleName='control'>
<button styleName='control-newNoteButton'
onClick={this.handleNewNoteButtonClick}>
<img styleName='iconTag' src='../resources/icon/icon-newnote.svg' />
<img src='../resources/icon/icon-newnote.svg' />
<span styleName='control-newNoteButton-tooltip'>
{i18n.__('Make a note')} {OSX ? '⌘' : i18n.__('Ctrl')} + N
</span>

View File

@@ -1138,7 +1138,7 @@ class NoteList extends React.Component {
}
onClick={(e) => this.handleListStyleButtonClick(e, 'DEFAULT')}
>
<img styleName='iconTag' src='../resources/icon/icon-column.svg' />
<img src='../resources/icon/icon-column.svg' />
</button>
<button title={i18n.__('Compressed View')} styleName={config.listStyle === 'SMALL'
? 'control-button--active'
@@ -1146,7 +1146,7 @@ class NoteList extends React.Component {
}
onClick={(e) => this.handleListStyleButtonClick(e, 'SMALL')}
>
<img styleName='iconTag' src='../resources/icon/icon-column-list.svg' />
<img src='../resources/icon/icon-column-list.svg' />
</button>
</div>
</div>

View File

@@ -8,7 +8,7 @@ const PreferenceButton = ({
onClick
}) => (
<button styleName='top-menu-preference' onClick={(e) => onClick(e)}>
<img styleName='iconTag' src='../resources/icon/icon-setting.svg' />
<img src='../resources/icon/icon-setting.svg' />
<span styleName='tooltip'>{i18n.__('Preferences')}</span>
</button>
)

View File

@@ -362,14 +362,14 @@ class StorageItem extends React.Component {
<button styleName='header-addFolderButton'
onClick={(e) => this.handleAddFolderButtonClick(e)}
>
<img styleName='iconTag' src='../resources/icon/icon-plus.svg' />
<img src='../resources/icon/icon-plus.svg' />
</button>
}
<button styleName='header-info'
onClick={(e) => this.handleHeaderInfoClick(e)}
>
<span styleName='header-info-name'>
<span>
{isFolded ? _.truncate(storage.name, {length: 1, omission: ''}) : storage.name}
</span>
{isFolded &&
@@ -380,7 +380,7 @@ class StorageItem extends React.Component {
</button>
</div>
{this.state.isOpen &&
<div styleName='folderList' >
<div>
{folderList}
</div>
}

View File

@@ -440,7 +440,7 @@ class SideNav extends React.Component {
const style = {}
if (!isFolded) style.width = this.props.width
const isTagActive = location.pathname.match(/tag/)
const isTagActive = /tag/.test(location.pathname)
return (
<div className='SideNav'
styleName={isFolded ? 'root--folded' : 'root'}

View File

@@ -71,6 +71,7 @@ class TopBar extends React.Component {
this.refs.search.childNodes[0].blur
dispatch(push('/searched'))
e.preventDefault()
this.debouncedUpdateKeyword('')
}
handleKeyDown (e) {

View File

@@ -31,6 +31,8 @@ export const DEFAULT_CONFIG = {
toggleMode: OSX ? 'Command + Alt + M' : 'Ctrl + M',
deleteNote: OSX ? 'Command + Shift + Backspace' : 'Ctrl + Shift + Backspace',
pasteSmartly: OSX ? 'Command + Shift + V' : 'Ctrl + Shift + V',
insertDate: OSX ? 'Command + /' : 'Ctrl + /',
insertDateTime: OSX ? 'Command + Alt + /' : 'Ctrl + Shift + /',
toggleMenuBar: 'Alt'
},
ui: {
@@ -48,6 +50,7 @@ export const DEFAULT_CONFIG = {
fontFamily: win ? 'Consolas' : 'Monaco',
indentType: 'space',
indentSize: '2',
lineWrapping: true,
enableRulers: false,
rulers: [80, 120],
displayLineNumbers: true,
@@ -83,8 +86,10 @@ export const DEFAULT_CONFIG = {
breaks: true,
smartArrows: false,
allowCustomCSS: false,
customCSS: '',
customCSS: '/* Drop Your Custom CSS Code Here */',
sanitize: 'STRICT', // 'STRICT', 'ALLOW_STYLES', 'NONE'
mermaidHTMLLabel: false,
lineThroughCheckbox: true
},
blog: {
@@ -108,7 +113,6 @@ function validate (config) {
}
function _save (config) {
console.log(config)
window.localStorage.setItem('config', JSON.stringify(config))
}
@@ -141,7 +145,7 @@ function get () {
const theme = consts.THEMES.find(theme => theme.name === config.editor.theme)
if (theme) {
editorTheme.setAttribute('href', `../${theme.path}`)
editorTheme.setAttribute('href', theme.path)
} else {
config.editor.theme = 'default'
}
@@ -152,7 +156,13 @@ function get () {
function set (updates) {
const currentConfig = get()
const newConfig = Object.assign({}, DEFAULT_CONFIG, currentConfig, updates)
const arrangedUpdates = updates
if (updates.preview !== undefined && updates.preview.customCSS === '') {
arrangedUpdates.preview.customCSS = DEFAULT_CONFIG.preview.customCSS
}
const newConfig = Object.assign({}, DEFAULT_CONFIG, currentConfig, arrangedUpdates)
if (!validate(newConfig)) throw new Error('INVALID CONFIG')
_save(newConfig)
@@ -183,7 +193,7 @@ function set (updates) {
const newTheme = consts.THEMES.find(theme => theme.name === newConfig.editor.theme)
if (newTheme) {
editorTheme.setAttribute('href', `../${newTheme.path}`)
editorTheme.setAttribute('href', newTheme.path)
}
ipcRenderer.send('config-renew', {

View File

@@ -241,6 +241,10 @@ function migrateAttachments (markdownContent, storagePath, noteKey) {
* @returns {String} postprocessed HTML in which all :storage references are mapped to the actual paths.
*/
function fixLocalURLS (renderedHTML, storagePath) {
const encodedWin32SeparatorRegex = /%5C/g
const storageRegex = new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER, 'g')
const storageUrl = 'file:///' + path.join(storagePath, DESTINATION_FOLDER).replace(/\\/g, '/')
/*
A :storage reference is like `:storage/3b6f8bd6-4edd-4b15-96e0-eadc4475b564/f939b2c3.jpg`.
@@ -250,8 +254,7 @@ function fixLocalURLS (renderedHTML, storagePath) {
- `(?:\\\/|%5C)` match the path seperator. `\\\/` for posix systems and `%5C` for windows.
*/
return renderedHTML.replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '(?:(?:\\\/|%5C)[-.\\w]+)+', 'g'), function (match) {
var encodedPathSeparators = new RegExp(mdurl.encode(path.win32.sep) + '|' + mdurl.encode(path.posix.sep), 'g')
return match.replace(encodedPathSeparators, path.sep).replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER, 'g'), 'file:///' + path.join(storagePath, DESTINATION_FOLDER))
return match.replace(encodedWin32SeparatorRegex, '/').replace(storageRegex, storageUrl)
})
}
@@ -617,8 +620,6 @@ function deleteAttachmentsNotPresentInNote (markdownContent, storageKey, noteKey
}
})
})
} else {
console.info('Attachment folder ("' + attachmentFolder + '") did not exist..')
}
}

View File

@@ -19,6 +19,7 @@
.control
padding 25px 0px
text-align center
display: flex
.control-button
width 240px

View File

@@ -225,7 +225,7 @@ class FolderItem extends React.Component {
<div styleName='folderItem-left'
style={{borderColor: folder.color}}
>
<span styleName='folderItem-left-name'>{folder.name}</span>
<span>{folder.name}</span>
<span styleName='folderItem-left-key'>({folder.key})</span>
</div>
<div styleName='folderItem-right'>
@@ -288,10 +288,10 @@ class Handle extends React.Component {
class SortableFolderItemComponent extends React.Component {
render () {
const StyledHandle = CSSModules(Handle, this.props.styles)
const StyledHandle = CSSModules(Handle, styles)
const DragHandle = SortableHandle(StyledHandle)
const StyledFolderItem = CSSModules(FolderItem, this.props.styles)
const StyledFolderItem = CSSModules(FolderItem, styles)
return (
<div>

View File

@@ -22,7 +22,7 @@ class FolderList extends React.Component {
})
return (
<div styleName='folderList'>
<div>
{folderList.length > 0
? folderList
: <div styleName='folderList-empty'>{i18n.__('No Folders')}</div>

View File

@@ -173,6 +173,26 @@ class HotkeyTab extends React.Component {
/>
</div>
</div>
<div styleName='group-section'>
<div styleName='group-section-label'>{i18n.__('Insert Current Date')}</div>
<div styleName='group-section-control'>
<input styleName='group-section-control-input'
value={config.hotkey.insertDate}
type='text'
disabled='true'
/>
</div>
</div>
<div styleName='group-section'>
<div styleName='group-section-label'>{i18n.__('Insert Current Date and Time')}</div>
<div styleName='group-section-control'>
<input styleName='group-section-control-input'
value={config.hotkey.insertDateTime}
type='text'
disabled='true'
/>
</div>
</div>
<div styleName='group-control'>
<button styleName='group-control-leftButton'
onClick={(e) => this.handleHintToggleButtonClick(e)}

View File

@@ -14,6 +14,7 @@ import { getLanguages } from 'browser/lib/Languages'
import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
const OSX = global.process.platform === 'darwin'
const WIN = global.process.platform === 'win32'
const electron = require('electron')
const ipc = electron.ipcRenderer
@@ -91,6 +92,7 @@ class UiTab extends React.Component {
enableRulers: this.refs.enableEditorRulers.value === 'true',
rulers: this.refs.editorRulers.value.replace(/[^0-9,]/g, '').split(','),
displayLineNumbers: this.refs.editorDisplayLineNumbers.checked,
lineWrapping: this.refs.editorLineWrapping.checked,
switchPreview: this.refs.editorSwitchPreview.value,
keyMap: this.refs.editorKeyMap.value,
snippetDefaultLanguage: this.refs.editorSnippetDefaultLanguage.value,
@@ -123,6 +125,7 @@ class UiTab extends React.Component {
breaks: this.refs.previewBreaks.checked,
smartArrows: this.refs.previewSmartArrows.checked,
sanitize: this.refs.previewSanitize.value,
mermaidHTMLLabel: this.refs.previewMermaidHTMLLabel.checked,
allowCustomCSS: this.refs.previewAllowCustomCSS.checked,
lineThroughCheckbox: this.refs.lineThroughCheckbox.checked,
customCSS: this.customCSSCM.getCodeMirror().getValue()
@@ -135,7 +138,7 @@ class UiTab extends React.Component {
const theme = consts.THEMES.find(theme => theme.name === newCodemirrorTheme)
if (theme) {
checkHighLight.setAttribute('href', `../${theme.path}`)
checkHighLight.setAttribute('href', theme.path)
}
}
@@ -545,6 +548,17 @@ class UiTab extends React.Component {
</label>
</div>
<div styleName='group-checkBoxSection'>
<label>
<input onChange={(e) => this.handleUIChange(e)}
checked={this.state.config.editor.lineWrapping}
ref='editorLineWrapping'
type='checkbox'
/>&nbsp;
{i18n.__('Wrap line in Snippet Note')}
</label>
</div>
<div styleName='group-checkBoxSection'>
<label>
<input onChange={(e) => this.handleUIChange(e)}
@@ -800,6 +814,16 @@ class UiTab extends React.Component {
</select>
</div>
</div>
<div styleName='group-checkBoxSection'>
<label>
<input onChange={(e) => this.handleUIChange(e)}
checked={this.state.config.preview.mermaidHTMLLabel}
ref='previewMermaidHTMLLabel'
type='checkbox'
/>&nbsp;
{i18n.__('Enable HTML label in mermaid flowcharts')}
</label>
</div>
<div styleName='group-section'>
<div styleName='group-section-label'>
{i18n.__('LaTeX Inline Open Delimiter')}
@@ -883,7 +907,6 @@ class UiTab extends React.Component {
onChange={e => this.handleUIChange(e)}
ref={e => (this.customCSSCM = e)}
value={config.preview.customCSS}
defaultValue={'/* Drop Your Custom CSS Code Here */\n'}
options={{
lineNumbers: true,
mode: 'css',

View File

@@ -147,7 +147,7 @@ class Preferences extends React.Component {
key={tab.target}
onClick={(e) => this.handleNavButtonClick(tab.target)(e)}
>
<span styleName='nav-button-label'>
<span>
{tab.label}
</span>
{isUiHotkeyTab ? this.haveToSaveNotif(tab[tab.label].type, tab[tab.label].message) : null}

View File

@@ -476,7 +476,8 @@ const reducer = combineReducers({
router: connectRouter(history)
})
const store = createStore(reducer, undefined, compose(
applyMiddleware(routerMiddleware(history)), DevTools.instrument()))
const store = createStore(reducer, undefined, process.env.NODE_ENV === 'development'
? compose(applyMiddleware(routerMiddleware(history)), DevTools.instrument())
: applyMiddleware(routerMiddleware(history)))
export { store, history }