1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-14 02:06:29 +00:00

Merge branch 'dev'

* dev:
  temporary setup
  0.4.5
  emit empty event(to create new record of today if not exists)
  MAIN_DETAIL_COPY, *_BY_SYNTAX, CLIENT_VERSION 追加
  debug ModeSelect component
  fix markdown style a little more
  Markdown styleを少し改善
  bump up version to 0.4.5 and change codesign path
  自動的にスクロールを合わせてくれる
  fix release path
  add electron-builder & modify deploy scripts
  bump up Ace editor
  Github release

Conflicts:
	package.json
This commit is contained in:
Rokt33r
2015-12-08 18:53:26 +09:00
10 changed files with 143 additions and 47 deletions

3
.gitignore vendored
View File

@@ -1,6 +1,5 @@
.env .env
node_modules/* node_modules/*
!node_modules/boost !node_modules/boost
Boost-darwin-x64/ dist/
backup/
compiled compiled

View File

@@ -162,6 +162,7 @@ export default class ArticleDetail extends React.Component {
} }
handleClipboardButtonClick (e) { handleClipboardButtonClick (e) {
activityRecord.emit('MAIN_DETAIL_COPY')
clipboard.writeText(this.props.activeArticle.content) clipboard.writeText(this.props.activeArticle.content)
notify('Saved to Clipboard!', { notify('Saved to Clipboard!', {
body: 'Paste it wherever you want!' body: 'Paste it wherever you want!'
@@ -293,9 +294,9 @@ export default class ArticleDetail extends React.Component {
if (newArticle.title.length === 0) { if (newArticle.title.length === 0) {
newArticle.title = `Created at ${moment(newArticle.createdAt).format('YYYY/MM/DD HH:mm')}` newArticle.title = `Created at ${moment(newArticle.createdAt).format('YYYY/MM/DD HH:mm')}`
} }
activityRecord.emit('ARTICLE_CREATE') activityRecord.emit('ARTICLE_CREATE', {mode: newArticle.mode})
} else { } else {
activityRecord.emit('ARTICLE_UPDATE') activityRecord.emit('ARTICLE_UPDATE', {mode: newArticle.mode})
} }
dispatch(updateArticle(newArticle)) dispatch(updateArticle(newArticle))
@@ -435,7 +436,34 @@ export default class ArticleDetail extends React.Component {
handleTogglePreviewButtonClick (e) { handleTogglePreviewButtonClick (e) {
if (this.state.article.mode === 'markdown') { if (this.state.article.mode === 'markdown') {
this.setState({previewMode: !this.state.previewMode}) if (!this.state.previewMode) {
let cursorPosition = this.refs.code.getCursorPosition()
let firstVisibleRow = this.refs.code.getFirstVisibleRow()
this.setState({
previewMode: true,
cursorPosition,
firstVisibleRow
}, function () {
let previewEl = ReactDOM.findDOMNode(this.refs.preview)
let anchors = previewEl.querySelectorAll('.lineAnchor')
for (let i = 0; i < anchors.length; i++) {
if (parseInt(anchors[i].dataset.key, 10) > cursorPosition.row || i === anchors.length - 1) {
var targetAnchor = anchors[i > 0 ? i - 1 : 0]
previewEl.scrollTop = targetAnchor.offsetTop - 100
break
}
}
})
} else {
this.setState({
previewMode: false
}, function () {
console.log(this.state.cursorPosition)
this.refs.code.moveCursorTo(this.state.cursorPosition.row, this.state.cursorPosition.column)
this.refs.code.scrollToLine(this.state.firstVisibleRow)
this.refs.code.editor.focus()
})
}
} }
} }
@@ -524,7 +552,7 @@ export default class ArticleDetail extends React.Component {
</div> </div>
{this.state.previewMode {this.state.previewMode
? <MarkdownPreview content={this.state.article.content}/> ? <MarkdownPreview ref='preview' content={this.state.article.content}/>
: (<CodeEditor : (<CodeEditor
ref='code' ref='code'
onChange={(e, value) => this.handleContentChange(e, value)} onChange={(e, value) => this.handleContentChange(e, value)}

View File

@@ -1,36 +1,38 @@
marked() marked()
h1, h2, h3, h4, h5, h6, p
&:first-child
margin-top 0
hr hr
border-top none border-top none
border-bottom solid 1px borderColor border-bottom solid 1px borderColor
margin 15px 0 margin 15px 0
h1, h2, h3, h4, h5, h6
margin 0 0 15px
font-weight 600
* + h1, * + h2, * + h3, * + h4, * + h5, * + h6
margin-top 25px
h1 h1
font-size 2em font-size 2em
border-bottom solid 2px borderColor border-bottom solid 2px borderColor
margin 0.33em auto 0.67em line-height 2.333em
h2 h2
font-size 1.5em font-size 1.66em
margin 0.42em auto 0.83em line-height 2.07em
h3 h3
font-size 1.17em font-size 1.33em
margin 0.5em auto 1em line-height 1.6625em
h4 h4
font-size 1em font-size 1.15em
margin 0.67em auto 1.33em line-height 1.4375em
h5 h5
font-size 0.83em font-size 1em
margin 0.84em auto 1.67em line-height 1.25em
h6 h6
font-size 0.67em font-size 0.8em
margin 1.16em auto 2.33em line-height 1em
h1, h2, h3, h4, h5, h6
font-weight 700 * + p, * + blockquote, * + ul, * + ol, * + pre
line-height 1.8em margin-top 15px
p p
line-height 1.8em line-height 1.9em
margin 15px 0 25px margin 0 0 15px
img img
max-width 100% max-width 100%
strong strong
@@ -41,15 +43,17 @@ marked()
text-decoration line-through text-decoration line-through
blockquote blockquote
border-left solid 4px brandBorderColor border-left solid 4px brandBorderColor
margin 15px 0 25px margin 0 0 15px
padding 0 25px padding 0 25px
ul ul
list-style-type disc list-style-type disc
padding-left 35px padding-left 35px
margin-bottom 35px margin-bottom 15px
li li
display list-item display list-item
line-height 1.8em line-height 1.8em
&>li>ul, &>li>ol
margin 0
&>li>ul &>li>ul
list-style-type circle list-style-type circle
&>li>ul &>li>ul
@@ -57,10 +61,12 @@ marked()
ol ol
list-style-type decimal list-style-type decimal
padding-left 35px padding-left 35px
margin-bottom 35px margin-bottom 15px
li li
display list-item display list-item
line-height 1.8em line-height 1.8em
&>li>ul, &>li>ol
margin 0
code code
font-family Monaco, Menlo, 'Ubuntu Mono', Consolas, source-code-pro, monospace; font-family Monaco, Menlo, 'Ubuntu Mono', Consolas, source-code-pro, monospace;
padding 2px 4px padding 2px 4px
@@ -70,15 +76,19 @@ marked()
color black color black
text-decoration none text-decoration none
background-color #F6F6F6 background-color #F6F6F6
margin-right 2px
* + code
margin-left 2px
pre pre
padding 5px padding 5px
border solid 1px borderColor border solid 1px borderColor
border-radius 5px border-radius 5px
overflow-x auto overflow-x auto
margin 15px 0 25px margin 0 0 15px
background-color #F6F6F6 background-color #F6F6F6
line-height 1.35em line-height 1.35em
&>code &>code
margin 0
padding 0 padding 0
border none border none
border-radius 0 border-radius 0

12
builder-config.json Normal file
View File

@@ -0,0 +1,12 @@
{
"osx" : {
"title": "Boost Installer",
// "background": "resources/background.png",
"icon": "resources/app.icns",
"icon-size": 80,
"contents": [
{ "x": 438, "y": 344, "type": "link", "path": "/Applications" },
{ "x": 192, "y": 344, "type": "file" }
]
}
}

View File

@@ -4,6 +4,9 @@ import keygen from 'boost/keygen'
import dataStore from 'boost/dataStore' import dataStore from 'boost/dataStore'
import { request, WEB_URL } from 'boost/api' import { request, WEB_URL } from 'boost/api'
const electron = require('electron')
const version = electron.remote.app.getVersion()
function isSameDate (a, b) { function isSameDate (a, b) {
a = moment(a).utcOffset(+540).format('YYYYMMDD') a = moment(a).utcOffset(+540).format('YYYYMMDD')
b = moment(b).utcOffset(+540).format('YYYYMMDD') b = moment(b).utcOffset(+540).format('YYYYMMDD')
@@ -16,6 +19,7 @@ export function init () {
if (records == null) { if (records == null) {
saveAllRecords([]) saveAllRecords([])
} }
emit(null)
postRecords() postRecords()
if (window != null) { if (window != null) {
@@ -81,7 +85,7 @@ export function postRecords (data) {
}) })
} }
export function emit (type, data) { export function emit (type, data = {}) {
let records = getAllRecords() let records = getAllRecords()
let index = _.findIndex(records, record => { let index = _.findIndex(records, record => {
@@ -94,7 +98,6 @@ export function emit (type, data) {
records.push(todayRecord) records.push(todayRecord)
} }
else todayRecord = records[index] else todayRecord = records[index]
console.log(type)
switch (type) { switch (type) {
case 'ARTICLE_CREATE': case 'ARTICLE_CREATE':
case 'ARTICLE_UPDATE': case 'ARTICLE_UPDATE':
@@ -104,6 +107,7 @@ export function emit (type, data) {
case 'FOLDER_DESTROY': case 'FOLDER_DESTROY':
case 'FINDER_OPEN': case 'FINDER_OPEN':
case 'FINDER_COPY': case 'FINDER_COPY':
case 'MAIN_DETAIL_COPY':
todayRecord[type] = todayRecord[type] == null todayRecord[type] = todayRecord[type] == null
? 1 ? 1
: todayRecord[type] + 1 : todayRecord[type] + 1
@@ -111,9 +115,26 @@ export function emit (type, data) {
break break
} }
// Count ARTICLE_CREATE and ARTICLE_UPDATE again by syntax
if ((type === 'ARTICLE_CREATE' || type === 'ARTICLE_UPDATE') && data.mode != null) {
let recordKey = type + '_BY_SYNTAX'
if (todayRecord[recordKey] == null) todayRecord[recordKey] = {}
todayRecord[recordKey][data.mode] = todayRecord[recordKey][data.mode] == null
? 1
: todayRecord[recordKey][data.mode] + 1
}
let storeData = dataStore.getData() let storeData = dataStore.getData()
todayRecord.FOLDER_COUNT = _.isArray(storeData.folders) ? storeData.folders.length : 0 todayRecord.FOLDER_COUNT = _.isArray(storeData.folders) ? storeData.folders.length : 0
todayRecord.ARTICLE_COUNT = _.isArray(storeData.articles) ? storeData.articles.length : 0 todayRecord.ARTICLE_COUNT = _.isArray(storeData.articles) ? storeData.articles.length : 0
todayRecord.CLIENT_VERSION = version
todayRecord.SYNTAX_COUNT = storeData.articles.reduce((sum, article) => {
if (sum[article.mode] == null) sum[article.mode] = 1
else sum[article.mode]++
return sum
}, {})
saveAllRecords(records) saveAllRecords(records)
} }

View File

@@ -30,6 +30,7 @@ module.exports = React.createClass({
editor.renderer.setShowGutter(true) editor.renderer.setShowGutter(true)
editor.setTheme('ace/theme/xcode') editor.setTheme('ace/theme/xcode')
editor.clearSelection() editor.clearSelection()
editor.moveCursorTo(0, 0)
editor.setReadOnly(!!this.props.readOnly) editor.setReadOnly(!!this.props.readOnly)
@@ -50,16 +51,14 @@ module.exports = React.createClass({
this.props.onChange(e, value) this.props.onChange(e, value)
} }
}.bind(this)) }.bind(this))
this.setState({editor: editor})
}, },
componentDidUpdate: function (prevProps) { componentDidUpdate: function (prevProps) {
if (this.state.editor.getValue() !== this.props.code) { if (this.editor.getValue() !== this.props.code) {
this.state.editor.setValue(this.props.code) this.editor.setValue(this.props.code)
this.state.editor.clearSelection() this.editor.clearSelection()
} }
if (prevProps.mode !== this.props.mode) { if (prevProps.mode !== this.props.mode) {
var session = this.state.editor.getSession() var session = this.editor.getSession()
let mode = _.findWhere(modes, {name: this.props.mode}) let mode = _.findWhere(modes, {name: this.props.mode})
let syntaxMode = mode != null let syntaxMode = mode != null
? mode.mode ? mode.mode
@@ -67,6 +66,18 @@ module.exports = React.createClass({
session.setMode('ace/mode/' + syntaxMode) session.setMode('ace/mode/' + syntaxMode)
} }
}, },
getFirstVisibleRow: function () {
return this.editor.getFirstVisibleRow()
},
getCursorPosition: function () {
return this.editor.getCursorPosition()
},
moveCursorTo: function (row, col) {
this.editor.moveCursorTo(row, col)
},
scrollToLine: function (num) {
this.editor.scrollToLine(num, false, false)
},
render: function () { render: function () {
return ( return (
<div ref='target' className={this.props.className == null ? 'CodeEditor' : 'CodeEditor ' + this.props.className}></div> <div ref='target' className={this.props.className == null ? 'CodeEditor' : 'CodeEditor ' + this.props.className}></div>

View File

@@ -161,8 +161,8 @@ export default class ModeSelect extends React.Component {
let filteredOptions = modes let filteredOptions = modes
.filter(mode => { .filter(mode => {
let search = this.state.search let search = this.state.search
let nameMatched = mode.name.match(search) let nameMatched = mode.name.match(_.escapeRegExp(search))
let aliasMatched = _.some(mode.alias, alias => alias.match(search)) let aliasMatched = _.some(mode.alias, alias => alias.match(_.escapeRegExp(search)))
return nameMatched || aliasMatched return nameMatched || aliasMatched
}) })
.map((mode, index) => { .map((mode, index) => {

View File

@@ -8,20 +8,31 @@ var md = markdownit({
highlight: function (str, lang) { highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) { if (lang && hljs.getLanguage(lang)) {
try { try {
return hljs.highlight(lang, str).value; return hljs.highlight(lang, str).value
} catch (__) {} } catch (__) {}
} }
try { try {
return hljs.highlightAuto(str).value; return hljs.highlightAuto(str).value
} catch (__) {} } catch (__) {}
return ''; // use external default escaping return ''
} }
}) })
md.use(emoji) md.use(emoji)
let originalRenderToken = md.renderer.renderToken
md.renderer.renderToken = function renderToken (tokens, idx, options) {
let token = tokens[idx]
let result = originalRenderToken.call(md.renderer, tokens, idx, options)
if (token.map != null) {
return result + '<a class=\'lineAnchor\' data-key=\'' + token.map[0] + '\'></a>'
}
return result
}
export default function markdown (content) { export default function markdown (content) {
if (content == null) content = '' if (content == null) content = ''
return md.render(content.toString()) return md.render(content.toString())
} }

View File

@@ -68,7 +68,7 @@ const modes = [
{ {
name: 'csharp', name: 'csharp',
label: 'C#', label: 'C#',
alias: ['cs'], alias: ['cs', 'c#'],
mode: 'csharp' mode: 'csharp'
}, },
{ {

View File

@@ -1,19 +1,22 @@
{ {
"name": "boost", "name": "boost",
"version": "0.4.4", "version": "0.4.4",
"version": "0.4.5",
"description": "Boost App", "description": "Boost App",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "BOOST_ENV=development electron ./main.js", "start": "BOOST_ENV=development electron ./main.js",
"webpack": "webpack-dev-server --hot --inline --config webpack.config.js", "webpack": "webpack-dev-server --hot --inline --config webpack.config.js",
"compile": "NODE_ENV=production webpack --config webpack.config.production.js", "compile": "NODE_ENV=production webpack --config webpack.config.production.js",
"build": "electron-packager ./ Boost --app-version=$npm_package_version $npm_package_config_platform $npm_package_config_version $npm_package_config_ignore --overwrite --asar", "pack:osx": "electron-packager ./ Boost --app-version=$npm_package_version $npm_package_config_platform $npm_package_config_version $npm_package_config_ignore --overwrite --out=\"dist\"",
"codesign": "codesign --verbose --deep --force --sign \"MAISIN solutions Inc.\" Boost-darwin-x64/Boost.app" "codesign": "codesign --verbose --deep --force --sign \"MAISIN solutions Inc.\" dist/Boost-darwin-x64/Boost.app",
"build:osx": "electron-builder \"dist/Boost-darwin-x64/Boost.app\" --platform=osx --out=\"dist\" --config=\"./builder-config.json\"",
"release": "electron-release --app=\"dist/Boost-darwin-x64/Boost.app\" --token=$(cat .env/.github-token) --repo=\"BoostIO/boost-releases\""
}, },
"config": { "config": {
"version": "--version=0.35.1 --app-bundle-id=com.maisin.boost", "version": "--version=0.35.3 --app-bundle-id=com.maisin.boost",
"platform": "--platform=darwin --arch=x64 --prune --icon=resources/app.icns", "platform": "--platform=darwin --arch=x64 --prune --icon=resources/app.icns",
"ignore": "--ignore=Boost-darwin-x64 --ignore=node_modules/devicon/icons --ignore=submodules/ace/(?!src-min)|submodules/ace/(?=src-min-noconflict)" "ignore": "--ignore=.env --ignore=Boost-darwin-x64 --ignore=node_modules/devicon/icons --ignore=submodules/ace/(?!src-min)|submodules/ace/(?=src-min-noconflict)"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -56,6 +59,7 @@
"css-loader": "^0.19.0", "css-loader": "^0.19.0",
"electron-packager": "^5.1.0", "electron-packager": "^5.1.0",
"electron-prebuilt": "^0.35.1", "electron-prebuilt": "^0.35.1",
"electron-release": "^2.2.0",
"nib": "^1.1.0", "nib": "^1.1.0",
"react": "^0.14.0", "react": "^0.14.0",
"react-dom": "^0.14.0", "react-dom": "^0.14.0",