仕事をする上でメモを取ることはめちゃくちゃ大切だと思います。エンジニアは特にそうだと思います。
私もよくメモを取るのですが、自分好みのメモ帳が存在しないので自作することにしました。
electron + vue.js でプロトタイプを作っていたのですが、調べていたとこ、boostnoteがOSSとして公開されていることを知りました。2年ほど前使っていてかなり良かったのですが、ちょっと気に入らない点があってやめてしました。
今回はOSSとして公開されているBoostnoteを引っ張ってきて、カスタマイズしていこうと思います。
GitHub - BoostIO/Boostnote: A markdown editor for developers on Mac, Windows and Linux.
成果物
写真だと上にタイトル入力画面追加したくらいしかわからないですね
とりあえず起動する
git clone git@github.com:BoostIO/Boostnote.git
cd boostnote
yarn
yarn run dev
Boostnote/build.md at master · BoostIO/Boostnote · GitHub
環境によっては最初のyarnが少し時間かかるかもしれません。
これだけでBoostnoteが起動します。
個人的にはGUIの操作がないぶん普通にインストールする楽なきがします
事前準備
特にないです。適当にドキュメント眺める程度です。
- Electron | Build cross platform desktop apps with JavaScript, HTML, and CSS.
- React – ユーザインターフェース構築のための JavaScript ライブラリ
- Expressive, dynamic, robust CSS — expressive, robust, feature-rich CSS preprocessor
- DevTools Extension | Electron
Reactのdevtoolがchromeに未インストールの場合は一応しときます。
electronでdev tool 使うにはなにか必要ぽっかったのですが普通に使えました。
いじってみる
以下、個人的に気に入らない部分をいじっていきます。
なんか変更したら更新していくと思います。
新規作成時にMarkdonw Note or Snippet Noteのモーダルが出てくる
Boostnoteのsnippet機能は使わないので、新規作成ですぐにマークダウンを生成してほしいので写真のモーダルはいらない。
この程度なら設定で変えられそうと思いながらソースを追っていったら
handleNewNoteButtonClick (e) {
const { location, dispatch, match: { params }, config } = this.props
const { storage, folder } = this.resolveTargetFolder()
if (config.ui.defaultNote === 'MARKDOWN_NOTE') {
createMarkdownNote(storage.key, folder.key, dispatch, location, params, config)
} else if (config.ui.defaultNote === 'SNIPPET_NOTE') {
createSnippetNote(storage.key, folder.key, dispatch, location, params, config)
} else {
modal.open(NewNoteModal, {
storage: storage.key,
folder: folder.key,
dispatch,
location,
params,
config
})
}
configで条件分岐していました。設定でオフにできそうです。
と思ったけど、100%使用しないのでごっそり削ります。
handleNewNoteButtonClick (e) {
const { location, dispatch, match: { params }, config } = this.props
const { storage, folder } = this.resolveTargetFolder()
createMarkdownNote(storage.key, folder.key, dispatch, location, params, config)
}
タグのスタイルが気に食わない
Before
After
個人的にはタグの頭の#が不要で、あと色も薄いので変えたい。
頭の#に関しては表示場所で追加してるだけなので、適当に目星をつけてgrepして直ぐに発見。
xxxx ~/w/Boostnote> git grep "#{tag"
browser/components/NoteItem.js: #{tagName}
browser/main/Detail/TagSelect.js: <span styleName='tag-label' style={textStyle} onClick={(e) => this.handleTagLabelClick(tag)}>#{tag}</span>
出てきた箇所の#を消します。
ついでに色を変更したいと思いみてみると、config.coloredTagsという部分を発見。
どうやら設定でかえられる?と思いつつ見てみると、タグ毎に色をつけられるらしい。
<TagSelect
ref='tags'
value={this.state.note.tags}
saveTagsAlphabetically={config.ui.saveTagsAlphabetically}
showTagsAlphabetically={config.ui.showTagsAlphabetically}
data={data}
onChange={this.handleUpdateTag.bind(this)}
coloredTags={config.coloredTags}
/>
なるほど・・
タグの生成時に自動で自分の好きな色を追加してしまおうと思ったが
そもそもタグに色つけないので、デフォルトのテーマカラーを変えました。
handleColorPickerConfirm (color) {
const { dispatch, config: {coloredTags} } = this.props
const { colorPicker: { tagName } } = this.state
const newColoredTags = Object.assign({}, coloredTags, {[tagName]: color.hex})
const config = { coloredTags: newColoredTags }
ConfigManager.set(config)
dispatch({
type: 'SET_CONFIG',
config
})
this.dismissColorPicker()
}
1行目がタイトルになるけど、タイトルは別に入力したい。
Qiitaとかはてブとかのの記事作成画面のように、タイトルはタイトル入力用のボックスに入力したい。
入力画面をスクロールするとプレビューも追随してスクロールするのがうざい。
入力画面をスクロールすると追随してPreview画面もスクロールしてくれるのですが、移動にアニメーションあってすごい鬱陶しいです。
これは親切な機能なのですがすごくもどかしい。アニメーションを無効にしたいと思います。その点Qiitaの記事作成画面は自然に追随してくれて良いですね!
このあたり、なんかめっちゃスクロールしてそうです。this.props.config.preview.scrollSync
とあってこれも設定で変えられそうに思いきや、追随を無効にしてくれるだけですね。アニメーションを無効にしたいのでやっぱりソースイジる必要がありました。
handleScroll (e) {
if (!this.props.config.preview.scrollSync) return
console.log('123445')
const previewDoc = _.get(this, 'refs.preview.refs.root.contentWindow.document')
const codeDoc = _.get(this, 'refs.code.editor.doc')
let srcTop, srcHeight, targetTop, targetHeight
if (this.userScroll) {
if (e.doc) {
srcTop = _.get(e, 'doc.scrollTop')
srcHeight = _.get(e, 'doc.height')
targetTop = _.get(previewDoc, 'body.scrollTop')
targetHeight = _.get(previewDoc, 'body.scrollHeight')
} else {
srcTop = _.get(previewDoc, 'body.scrollTop')
srcHeight = _.get(previewDoc, 'body.scrollHeight')
targetTop = _.get(codeDoc, 'scrollTop')
targetHeight = _.get(codeDoc, 'height')
}
const distance = (targetHeight * srcTop / srcHeight) - targetTop
const framerate = 1000 / 60
const frames = 20
const refractory = frames * framerate
this.userScroll = false
let frame = 0
let scrollPos, time
const timer = setInterval(() => {
time = frame / frames
scrollPos = time < 0.5
? 2 * time * time // ease in
: -1 + (4 - 2 * time) * time // ease out
if (e.doc) _.set(previewDoc, 'body.scrollTop', targetTop + scrollPos * distance)
else _.get(this, 'refs.code.editor').scrollTo(0, targetTop + scrollPos * distance)
if (frame >= frames) {
clearInterval(timer)
setTimeout(() => { this.userScroll = true }, refractory)
}
frame++
}, framerate)
}
}
下の方を少しだけ変更してアニメーションを無効にします。
ショートカットを追加する
- 時間がある時に更新
Buildする (Help me)
grunt pre-build
をすると/distにboostnoteが生成される。
ただこれを起動するとロード画面のまま起動せず、devtoolを見てみると、
Uncaught TypeError: Cannot read property 'apply' of undefined
と出てくる。
これで検索するとgrup4とかでてくるけど、つかってなさそうだし。
そもそもローカルでもbuildできないように制限されてるのかな?そんなことはないと思うけど。
どなたかわかる方、コメントよろしくおねがいします。
感想
- git clone してすぐに起動できるが素晴らしすぎる。
- ソースコードの質の高さは判断できないがが、シンプルに実装されていて読みやすい
- 今回いじった部分ではファイルの行数がそこまで多くなかった。
- かなり素直に実装されていて、React触ったことなくてもなんとなく処理を追うことができた。
- Javascriptの文法も若干見たことがなかったものがあったり、ちょっぴり楽しかった。
- アプリとか作るの好きな人はソース追ってて楽しいと思う。
React勉強したい人は絶対cloneしてソース追ってみるべき
これだけのアプリのソースが無料で公開されているのでそう思いました。