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

Merge branch 'master' into text-expansion-support

This commit is contained in:
Junyoung Choi (Sai)
2018-04-26 16:39:52 -07:00
committed by GitHub
42 changed files with 1122 additions and 347 deletions

View File

@@ -3,10 +3,7 @@ import React from 'react'
import _ from 'lodash'
import CodeMirror from 'codemirror'
import 'codemirror-mode-elixir'
import path from 'path'
import copyImage from 'browser/main/lib/dataApi/copyImage'
import { findStorage } from 'browser/lib/findStorage'
import fs from 'fs'
import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement'
import eventEmitter from 'browser/main/lib/eventEmitter'
import iconv from 'iconv-lite'
import crypto from 'crypto'
@@ -354,23 +351,13 @@ export default class CodeEditor extends React.Component {
this.editor.setCursor(cursor)
}
handleDropImage (e) {
e.preventDefault()
const ValidImageTypes = ['image/gif', 'image/jpeg', 'image/png']
const file = e.dataTransfer.files[0]
const filePath = file.path
const filename = path.basename(filePath)
const fileType = file['type']
copyImage(filePath, this.props.storageKey).then((imagePath) => {
var showPreview = ValidImageTypes.indexOf(fileType) > 0
const imageMd = `${showPreview ? '!' : ''}[${filename}](${path.join('/:storage', imagePath)})`
this.insertImageMd(imageMd)
})
handleDropImage (dropEvent) {
dropEvent.preventDefault()
const {storageKey, noteKey} = this.props
attachmentManagement.handleAttachmentDrop(this, storageKey, noteKey, dropEvent)
}
insertImageMd (imageMd) {
insertAttachmentMd (imageMd) {
this.editor.replaceSelection(imageMd)
}
@@ -396,24 +383,8 @@ export default class CodeEditor extends React.Component {
return prevChar === '](' && nextChar === ')'
}
if (dataTransferItem.type.match('image')) {
const blob = dataTransferItem.getAsFile()
const reader = new FileReader()
let base64data
reader.readAsDataURL(blob)
reader.onloadend = () => {
base64data = reader.result.replace(/^data:image\/png;base64,/, '')
base64data += base64data.replace('+', ' ')
const binaryData = new Buffer(base64data, 'base64').toString('binary')
const imageName = Math.random().toString(36).slice(-16)
const storagePath = findStorage(this.props.storageKey).path
const imageDir = path.join(storagePath, 'images')
if (!fs.existsSync(imageDir)) fs.mkdirSync(imageDir)
const imagePath = path.join(imageDir, `${imageName}.png`)
fs.writeFile(imagePath, binaryData, 'binary')
const imageMd = `![${imageName}](${path.join('/:storage', `${imageName}.png`)})`
this.insertImageMd(imageMd)
}
const {storageKey, noteKey} = this.props
attachmentManagement.handlePastImageEvent(this, storageKey, noteKey, dataTransferItem)
} else if (this.props.fetchUrlTitle && isURL(pastedTxt) && !isInLinkTag(editor)) {
this.handlePasteUrl(e, editor, pastedTxt)
}

View File

@@ -5,7 +5,7 @@ import styles from './MarkdownEditor.styl'
import CodeEditor from 'browser/components/CodeEditor'
import MarkdownPreview from 'browser/components/MarkdownPreview'
import eventEmitter from 'browser/main/lib/eventEmitter'
import {findStorage} from 'browser/lib/findStorage'
import { findStorage } from 'browser/lib/findStorage'
class MarkdownEditor extends React.Component {
constructor (props) {
@@ -223,7 +223,7 @@ class MarkdownEditor extends React.Component {
}
render () {
const { className, value, config, storageKey } = this.props
const {className, value, config, storageKey, noteKey} = this.props
let editorFontSize = parseInt(config.editor.fontSize, 10)
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
@@ -263,6 +263,7 @@ class MarkdownEditor extends React.Component {
displayLineNumbers={config.editor.displayLineNumbers}
scrollPastEnd={config.editor.scrollPastEnd}
storageKey={storageKey}
noteKey={noteKey}
fetchUrlTitle={config.editor.fetchUrlTitle}
onChange={(e) => this.handleChange(e)}
onBlur={(e) => this.handleBlur(e)}

View File

@@ -13,9 +13,11 @@ import htmlTextHelper from 'browser/lib/htmlTextHelper'
import copy from 'copy-to-clipboard'
import mdurl from 'mdurl'
import exportNote from 'browser/main/lib/dataApi/exportNote'
import {escapeHtmlCharacters} from 'browser/lib/utils'
import { escapeHtmlCharacters } from 'browser/lib/utils'
const { remote } = require('electron')
const attachmentManagement = require('../main/lib/dataApi/attachmentManagement')
const { app } = remote
const path = require('path')
const dialog = remote.dialog
@@ -391,13 +393,11 @@ export default class MarkdownPreview extends React.Component {
value = value.replace(codeBlock, htmlTextHelper.encodeEntities(codeBlock))
})
}
this.refs.root.contentWindow.document.body.innerHTML = this.markdown.render(value)
let renderedHTML = this.markdown.render(value)
this.refs.root.contentWindow.document.body.innerHTML = attachmentManagement.fixLocalURLS(renderedHTML, storagePath)
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('a'), (el) => {
this.fixDecodedURI(el)
el.href = this.markdown.normalizeLinkText(el.href)
if (!/\/:storage/.test(el.href)) return
el.href = `file:///${this.markdown.normalizeLinkText(path.join(storagePath, 'images', path.basename(el.href)))}`
el.addEventListener('click', this.anchorClickHandler)
})
@@ -409,12 +409,6 @@ export default class MarkdownPreview extends React.Component {
el.addEventListener('click', this.linkClickHandler)
})
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('img'), (el) => {
el.src = this.markdown.normalizeLinkText(el.src)
if (!/\/:storage/.test(el.src)) return
el.src = `file:///${this.markdown.normalizeLinkText(path.join(storagePath, 'images', path.basename(el.src)))}`
})
codeBlockTheme = consts.THEMES.some((_theme) => _theme === codeBlockTheme)
? codeBlockTheme
: 'default'
@@ -523,6 +517,15 @@ export default class MarkdownPreview extends React.Component {
}
handlelinkClick (e) {
e.preventDefault()
e.stopPropagation()
const href = e.target.href
if (href.match(/^http/i)) {
shell.openExternal(href)
return
}
const noteHash = e.target.href.split('/').pop()
// this will match the new uuid v4 hash and the old hash
// e.g.

View File

@@ -88,7 +88,7 @@ class MarkdownSplitEditor extends React.Component {
}
render () {
const { config, value, storageKey } = this.props
const {config, value, storageKey, noteKey} = this.props
const storage = findStorage(storageKey)
let editorFontSize = parseInt(config.editor.fontSize, 10)
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
@@ -115,6 +115,7 @@ class MarkdownSplitEditor extends React.Component {
scrollPastEnd={config.editor.scrollPastEnd}
fetchUrlTitle={config.editor.fetchUrlTitle}
storageKey={storageKey}
noteKey={noteKey}
onChange={this.handleOnChange.bind(this)}
onScroll={this.handleScroll.bind(this)}
/>

View File

@@ -51,7 +51,7 @@ const SideNavFilter = ({
</button>
<button styleName={isTrashedActive ? 'menu-button-trash--active' : 'menu-button'}
onClick={handleTrashedButtonClick}
onClick={handleTrashedButtonClick} onContextMenu={handleFilterButtonContextMenu}
>
<div styleName='iconWrap'>
<img src={isTrashedActive
@@ -60,7 +60,7 @@ const SideNavFilter = ({
}
/>
</div>
<span onContextMenu={handleFilterButtonContextMenu} styleName='menu-button-label'>{i18n.__('Trash')}</span>
<span styleName='menu-button-label'>{i18n.__('Trash')}</span>
<span styleName='counters'>{counterDelNote}</span>
</button>

View File

@@ -9,16 +9,26 @@ import CSSModules from 'browser/lib/CSSModules'
/**
* @param {string} name
* @param {Function} handleClickTagListItem
* @param {Function} handleClickNarrowToTag
* @param {bool} isActive
* @param {bool} isRelated
*/
const TagListItem = ({name, handleClickTagListItem, isActive, count}) => (
<button styleName={isActive ? 'tagList-item-active' : 'tagList-item'} onClick={() => handleClickTagListItem(name)}>
<span styleName='tagList-item-name'>
{`# ${name}`}
<span styleName='tagList-item-count'> {count}</span>
</span>
</button>
const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, isActive, isRelated, count}) => (
<div styleName='tagList-itemContainer'>
{isRelated
? <button styleName={isActive ? 'tagList-itemNarrow-active' : 'tagList-itemNarrow'} onClick={() => handleClickNarrowToTag(name)}>
<i className={isActive ? 'fa fa-minus-circle' : 'fa fa-plus-circle'} />
</button>
: <div styleName={isActive ? 'tagList-itemNarrow-active' : 'tagList-itemNarrow'} />
}
<button styleName={isActive ? 'tagList-item-active' : 'tagList-item'} onClick={() => handleClickTagListItem(name)}>
<span styleName='tagList-item-name'>
{`# ${name}`}
<span styleName='tagList-item-count'>{count}</span>
</span>
</button>
</div>
)
TagListItem.propTypes = {

View File

@@ -1,5 +1,9 @@
.tagList-itemContainer
display flex
.tagList-item
display flex
flex 1
width 100%
height 26px
background-color transparent
@@ -20,9 +24,16 @@
color $ui-button-default-color
background-color $ui-button-default--active-backgroundColor
.tagList-itemNarrow
composes tagList-item
flex none
width 20px
padding 0 4px
.tagList-item-active
background-color $ui-button-default--active-backgroundColor
display flex
flex 1
width 100%
height 26px
padding 0
@@ -36,10 +47,16 @@
background-color alpha($ui-button-default--active-backgroundColor, 60%)
transition 0.2s
.tagList-itemNarrow-active
composes tagList-item-active
flex none
width 20px
padding 0 4px
.tagList-item-name
display block
flex 1
padding 0 15px
padding 0 8px 0 4px
height 26px
line-height 26px
border-width 0 0 0 2px
@@ -49,7 +66,10 @@
text-overflow ellipsis
.tagList-item-count
padding 0 3px
float right
line-height 26px
padding-right 15px
font-size 13px
body[data-theme="white"]
.tagList-item