mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 01:36:22 +00:00
Merge branch 'master' into gallery
This commit is contained in:
@@ -14,6 +14,8 @@ import consts from 'browser/lib/consts'
|
||||
import fs from 'fs'
|
||||
const { ipcRenderer } = require('electron')
|
||||
import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
|
||||
import TurndownService from 'turndown'
|
||||
import { gfm } from 'turndown-plugin-gfm'
|
||||
|
||||
CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js'
|
||||
|
||||
@@ -57,9 +59,12 @@ export default class CodeEditor extends React.Component {
|
||||
}
|
||||
this.searchHandler = (e, msg) => this.handleSearch(msg)
|
||||
this.searchState = null
|
||||
this.scrollToLineHandeler = this.scrollToLine.bind(this)
|
||||
|
||||
this.formatTable = () => this.handleFormatTable()
|
||||
this.editorActivityHandler = () => this.handleEditorActivity()
|
||||
|
||||
this.turndownService = new TurndownService()
|
||||
}
|
||||
|
||||
handleSearch (msg) {
|
||||
@@ -125,6 +130,7 @@ export default class CodeEditor extends React.Component {
|
||||
componentDidMount () {
|
||||
const { rulers, enableRulers } = this.props
|
||||
const expandSnippet = this.expandSnippet.bind(this)
|
||||
eventEmitter.on('line:jump', this.scrollToLineHandeler)
|
||||
|
||||
const defaultSnippet = [
|
||||
{
|
||||
@@ -475,7 +481,13 @@ export default class CodeEditor extends React.Component {
|
||||
|
||||
moveCursorTo (row, col) {}
|
||||
|
||||
scrollToLine (num) {}
|
||||
scrollToLine (event, num) {
|
||||
const cursor = {
|
||||
line: num,
|
||||
ch: 1
|
||||
}
|
||||
this.editor.setCursor(cursor)
|
||||
}
|
||||
|
||||
focus () {
|
||||
this.editor.focus()
|
||||
@@ -538,7 +550,11 @@ export default class CodeEditor extends React.Component {
|
||||
)
|
||||
return prevChar === '](' && nextChar === ')'
|
||||
}
|
||||
if (dataTransferItem.type.match('image')) {
|
||||
|
||||
const pastedHtml = clipboardData.getData('text/html')
|
||||
if (pastedHtml !== '') {
|
||||
this.handlePasteHtml(e, editor, pastedHtml)
|
||||
} else if (dataTransferItem.type.match('image')) {
|
||||
attachmentManagement.handlePastImageEvent(
|
||||
this,
|
||||
storageKey,
|
||||
@@ -608,6 +624,12 @@ export default class CodeEditor extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
handlePasteHtml (e, editor, pastedHtml) {
|
||||
e.preventDefault()
|
||||
const markdown = this.turndownService.turndown(pastedHtml)
|
||||
editor.replaceSelection(markdown)
|
||||
}
|
||||
|
||||
mapNormalResponse (response, pastedTxt) {
|
||||
return this.decodeResponse(response).then(body => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
@@ -6,6 +6,7 @@ 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 ConfigManager from 'browser/main/lib/ConfigManager'
|
||||
|
||||
class MarkdownEditor extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -18,7 +19,7 @@ class MarkdownEditor extends React.Component {
|
||||
this.supportMdSelectionBold = [16, 17, 186]
|
||||
|
||||
this.state = {
|
||||
status: 'PREVIEW',
|
||||
status: props.config.editor.switchPreview === 'RIGHTCLICK' ? props.config.editor.delfaultStatus : 'PREVIEW',
|
||||
renderValue: props.value,
|
||||
keyPressed: new Set(),
|
||||
isLocked: false
|
||||
@@ -64,6 +65,10 @@ class MarkdownEditor extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
setValue (value) {
|
||||
this.refs.code.setValue(value)
|
||||
}
|
||||
|
||||
handleChange (e) {
|
||||
this.value = this.refs.code.value
|
||||
this.props.onChange(e)
|
||||
@@ -72,9 +77,7 @@ class MarkdownEditor extends React.Component {
|
||||
handleContextMenu (e) {
|
||||
const { config } = this.props
|
||||
if (config.editor.switchPreview === 'RIGHTCLICK') {
|
||||
const newStatus = this.state.status === 'PREVIEW'
|
||||
? 'CODE'
|
||||
: 'PREVIEW'
|
||||
const newStatus = this.state.status === 'PREVIEW' ? 'CODE' : 'PREVIEW'
|
||||
this.setState({
|
||||
status: newStatus
|
||||
}, () => {
|
||||
@@ -84,6 +87,10 @@ class MarkdownEditor extends React.Component {
|
||||
this.refs.preview.focus()
|
||||
}
|
||||
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
|
||||
|
||||
const newConfig = Object.assign({}, config)
|
||||
newConfig.editor.delfaultStatus = newStatus
|
||||
ConfigManager.set(newConfig)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -300,6 +307,7 @@ class MarkdownEditor extends React.Component {
|
||||
noteKey={noteKey}
|
||||
customCSS={config.preview.customCSS}
|
||||
allowCustomCSS={config.preview.allowCustomCSS}
|
||||
lineThroughCheckbox={config.preview.lineThroughCheckbox}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -84,7 +84,6 @@ function buildStyle (
|
||||
url('${appPath}/resources/fonts/MaterialIcons-Regular.woff') format('woff'),
|
||||
url('${appPath}/resources/fonts/MaterialIcons-Regular.ttf') format('truetype');
|
||||
}
|
||||
${allowCustomCSS ? customCSS : ''}
|
||||
${markdownStyle}
|
||||
|
||||
body {
|
||||
@@ -92,6 +91,11 @@ body {
|
||||
font-size: ${fontSize}px;
|
||||
${scrollPastEnd && 'padding-bottom: 90vh;'}
|
||||
}
|
||||
@media print {
|
||||
body {
|
||||
padding-bottom: initial;
|
||||
}
|
||||
}
|
||||
code {
|
||||
font-family: '${codeBlockFontFamily.join("','")}';
|
||||
background-color: rgba(0,0,0,0.04);
|
||||
@@ -148,6 +152,8 @@ body p {
|
||||
display: none
|
||||
}
|
||||
}
|
||||
|
||||
${allowCustomCSS ? customCSS : ''}
|
||||
`
|
||||
}
|
||||
|
||||
@@ -329,9 +335,7 @@ export default class MarkdownPreview extends React.Component {
|
||||
allowCustomCSS,
|
||||
customCSS
|
||||
)
|
||||
let body = this.markdown.render(
|
||||
escapeHtmlCharacters(noteContent, { detectCodeBlock: true })
|
||||
)
|
||||
let body = this.markdown.render(noteContent)
|
||||
const files = [this.GetCodeThemeLink(codeBlockTheme), ...CSS_FILES]
|
||||
const attachmentsAbsolutePaths = attachmentManagement.getAbsolutePathsOfAttachmentsInContent(
|
||||
noteContent,
|
||||
@@ -488,10 +492,6 @@ export default class MarkdownPreview extends React.Component {
|
||||
eventEmitter.on('export:save-md', this.saveAsMdHandler)
|
||||
eventEmitter.on('export:save-html', this.saveAsHtmlHandler)
|
||||
eventEmitter.on('print', this.printHandler)
|
||||
eventEmitter.on('config-renew', () => {
|
||||
this.markdown.updateConfig()
|
||||
this.rewriteIframe()
|
||||
})
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
@@ -535,7 +535,8 @@ export default class MarkdownPreview extends React.Component {
|
||||
prevProps.smartQuotes !== this.props.smartQuotes ||
|
||||
prevProps.sanitize !== this.props.sanitize ||
|
||||
prevProps.smartArrows !== this.props.smartArrows ||
|
||||
prevProps.breaks !== this.props.breaks
|
||||
prevProps.breaks !== this.props.breaks ||
|
||||
prevProps.lineThroughCheckbox !== this.props.lineThroughCheckbox
|
||||
) {
|
||||
this.initMarkdown()
|
||||
this.rewriteIframe()
|
||||
@@ -897,6 +898,15 @@ export default class MarkdownPreview extends React.Component {
|
||||
return
|
||||
}
|
||||
|
||||
const regexIsLine = /^:line:[0-9]/
|
||||
if (regexIsLine.test(linkHash)) {
|
||||
const numberPattern = /\d+/g
|
||||
|
||||
const lineNumber = parseInt(linkHash.match(numberPattern)[0])
|
||||
eventEmitter.emit('line:jump', lineNumber)
|
||||
return
|
||||
}
|
||||
|
||||
// this will match the old link format storage.key-note.key
|
||||
// e.g.
|
||||
// 877f99c3268608328037-1c211eb7dcb463de6490
|
||||
|
||||
@@ -20,12 +20,18 @@ class MarkdownSplitEditor extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
setValue (value) {
|
||||
this.refs.code.setValue(value)
|
||||
}
|
||||
|
||||
handleOnChange () {
|
||||
this.value = this.refs.code.value
|
||||
this.props.onChange()
|
||||
}
|
||||
|
||||
handleScroll (e) {
|
||||
if (!this.props.config.preview.scrollSync) return
|
||||
|
||||
const previewDoc = _.get(this, 'refs.preview.refs.root.contentWindow.document')
|
||||
const codeDoc = _.get(this, 'refs.code.editor.doc')
|
||||
let srcTop, srcHeight, targetTop, targetHeight
|
||||
@@ -192,6 +198,7 @@ class MarkdownSplitEditor extends React.Component {
|
||||
noteKey={noteKey}
|
||||
customCSS={config.preview.customCSS}
|
||||
allowCustomCSS={config.preview.allowCustomCSS}
|
||||
lineThroughCheckbox={config.preview.lineThroughCheckbox}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -24,16 +24,19 @@ const TagElement = ({ tagName }) => (
|
||||
/**
|
||||
* @description Tag element list component.
|
||||
* @param {Array|null} tags
|
||||
* @param {boolean} showTagsAlphabetically
|
||||
* @return {React.Component}
|
||||
*/
|
||||
const TagElementList = tags => {
|
||||
const TagElementList = (tags, showTagsAlphabetically) => {
|
||||
if (!isArray(tags)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const tagElements = tags.map(tag => TagElement({ tagName: tag }))
|
||||
|
||||
return tagElements
|
||||
if (showTagsAlphabetically) {
|
||||
return _.sortBy(tags).map(tag => TagElement({ tagName: tag }))
|
||||
} else {
|
||||
return tags.map(tag => TagElement({ tagName: tag }))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +58,8 @@ const NoteItem = ({
|
||||
pathname,
|
||||
storageName,
|
||||
folderName,
|
||||
viewType
|
||||
viewType,
|
||||
showTagsAlphabetically
|
||||
}) => (
|
||||
<div
|
||||
styleName={isActive ? 'item--active' : 'item'}
|
||||
@@ -93,7 +97,7 @@ const NoteItem = ({
|
||||
<div styleName='item-bottom'>
|
||||
<div styleName='item-bottom-tagList'>
|
||||
{note.tags.length > 0
|
||||
? TagElementList(note.tags)
|
||||
? TagElementList(note.tags, showTagsAlphabetically)
|
||||
: <span
|
||||
style={{ fontStyle: 'italic', opacity: 0.5 }}
|
||||
styleName='item-bottom-tagList-empty'
|
||||
|
||||
@@ -7,18 +7,18 @@ import styles from './StorageList.styl'
|
||||
import CSSModules from 'browser/lib/CSSModules'
|
||||
|
||||
/**
|
||||
* @param {Array} storgaeList
|
||||
* @param {Array} storageList
|
||||
*/
|
||||
|
||||
const StorageList = ({storageList, isFolded}) => (
|
||||
<div styleName={isFolded ? 'storageList-folded' : 'storageList'}>
|
||||
{storageList.length > 0 ? storageList : (
|
||||
<div styleName='storgaeList-empty'>No storage mount.</div>
|
||||
<div styleName='storageList-empty'>No storage mount.</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
StorageList.propTypes = {
|
||||
storgaeList: PropTypes.arrayOf(PropTypes.element).isRequired
|
||||
storageList: PropTypes.arrayOf(PropTypes.element).isRequired
|
||||
}
|
||||
export default CSSModules(StorageList, styles)
|
||||
|
||||
@@ -14,8 +14,8 @@ import CSSModules from 'browser/lib/CSSModules'
|
||||
* @param {bool} isRelated
|
||||
*/
|
||||
|
||||
const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, isActive, isRelated, count}) => (
|
||||
<div styleName='tagList-itemContainer'>
|
||||
const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, handleContextMenu, isActive, isRelated, count}) => (
|
||||
<div styleName='tagList-itemContainer' onContextMenu={e => handleContextMenu(e, name)}>
|
||||
{isRelated
|
||||
? <button styleName={isActive ? 'tagList-itemNarrow-active' : 'tagList-itemNarrow'} onClick={() => handleClickNarrowToTag(name)}>
|
||||
<i className={isActive ? 'fa fa-minus-circle' : 'fa fa-plus-circle'} />
|
||||
@@ -25,7 +25,7 @@ const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, isAc
|
||||
<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 styleName='tagList-item-count'>{count !== 0 ? count : ''}</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@ import styles from './TodoListPercentage.styl'
|
||||
*/
|
||||
|
||||
const TodoListPercentage = ({
|
||||
percentageOfTodo
|
||||
percentageOfTodo, onClearCheckboxClick
|
||||
}) => (
|
||||
<div styleName='percentageBar' style={{display: isNaN(percentageOfTodo) ? 'none' : ''}}>
|
||||
<div styleName='progressBar' style={{width: `${percentageOfTodo}%`}}>
|
||||
@@ -20,11 +20,15 @@ const TodoListPercentage = ({
|
||||
<p styleName='percentageText'>{percentageOfTodo}%</p>
|
||||
</div>
|
||||
</div>
|
||||
<div styleName='todoClear'>
|
||||
<p styleName='todoClearText' onClick={(e) => onClearCheckboxClick(e)}>clear</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
TodoListPercentage.propTypes = {
|
||||
percentageOfTodo: PropTypes.number.isRequired
|
||||
percentageOfTodo: PropTypes.number.isRequired,
|
||||
onClearCheckboxClick: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
export default CSSModules(TodoListPercentage, styles)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
.percentageBar
|
||||
display: flex
|
||||
position absolute
|
||||
top 72px
|
||||
right 0px
|
||||
@@ -30,6 +31,20 @@
|
||||
color #f4f4f4
|
||||
font-weight 600
|
||||
|
||||
.todoClear
|
||||
display flex
|
||||
justify-content: flex-end
|
||||
position absolute
|
||||
z-index 120
|
||||
width 100%
|
||||
height 100%
|
||||
padding 2px 10px
|
||||
|
||||
.todoClearText
|
||||
color #f4f4f4
|
||||
cursor pointer
|
||||
font-weight 500
|
||||
|
||||
body[data-theme="dark"]
|
||||
.percentageBar
|
||||
background-color #444444
|
||||
@@ -40,6 +55,9 @@ body[data-theme="dark"]
|
||||
.percentageText
|
||||
color $ui-dark-text-color
|
||||
|
||||
.todoClearText
|
||||
color $ui-dark-text-color
|
||||
|
||||
body[data-theme="solarized-dark"]
|
||||
.percentageBar
|
||||
background-color #002b36
|
||||
@@ -50,6 +68,9 @@ body[data-theme="solarized-dark"]
|
||||
.percentageText
|
||||
color #fdf6e3
|
||||
|
||||
.todoClearText
|
||||
color #fdf6e3
|
||||
|
||||
body[data-theme="monokai"]
|
||||
.percentageBar
|
||||
background-color: $ui-monokai-borderColor
|
||||
@@ -69,3 +90,6 @@ body[data-theme="dracula"]
|
||||
|
||||
.percentageText
|
||||
color $ui-dracula-text-color
|
||||
|
||||
.percentageText
|
||||
color $ui-dracula-text-color
|
||||
|
||||
@@ -373,6 +373,36 @@ for name, val in admonition_types
|
||||
color: val[color]
|
||||
content: val[icon]
|
||||
|
||||
dl
|
||||
margin 2rem 0
|
||||
padding 0
|
||||
display flex
|
||||
width 100%
|
||||
flex-wrap wrap
|
||||
align-items flex-start
|
||||
border-bottom 1px solid borderColor
|
||||
background-color tableHeadBgColor
|
||||
|
||||
dt
|
||||
border-top 1px solid borderColor
|
||||
font-weight bold
|
||||
text-align right
|
||||
overflow hidden
|
||||
flex-basis 20%
|
||||
padding 0.4rem 0.9rem
|
||||
box-sizing border-box
|
||||
|
||||
dd
|
||||
border-top 1px solid borderColor
|
||||
flex-basis 80%
|
||||
padding 0.4rem 0.9rem
|
||||
min-height 2.5rem
|
||||
background-color $ui-noteDetail-backgroundColor
|
||||
box-sizing border-box
|
||||
|
||||
dd + dd
|
||||
margin-left 20%
|
||||
|
||||
pre.fence
|
||||
flex-wrap wrap
|
||||
|
||||
@@ -456,6 +486,14 @@ body[data-theme="dark"]
|
||||
kbd
|
||||
background-color themeDarkBorder
|
||||
color themeDarkText
|
||||
dl
|
||||
border-color themeDarkBorder
|
||||
background-color themeDarkTableHead
|
||||
dt
|
||||
border-color themeDarkBorder
|
||||
dd
|
||||
border-color themeDarkBorder
|
||||
background-color themeDarkPreview
|
||||
|
||||
pre.fence
|
||||
.gallery
|
||||
@@ -491,6 +529,14 @@ body[data-theme="solarized-dark"]
|
||||
border-color themeSolarizedDarkTableBorder
|
||||
&:last-child
|
||||
border-right solid 1px themeSolarizedDarkTableBorder
|
||||
dl
|
||||
border-color themeDarkBorder
|
||||
background-color themeSolarizedDarkTableHead
|
||||
dt
|
||||
border-color themeDarkBorder
|
||||
dd
|
||||
border-color themeDarkBorder
|
||||
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||
|
||||
pre.fence
|
||||
.gallery
|
||||
@@ -529,6 +575,15 @@ body[data-theme="monokai"]
|
||||
kbd
|
||||
background-color themeDarkBackground
|
||||
|
||||
dl
|
||||
border-color themeDarkBorder
|
||||
background-color themeMonokaiTableHead
|
||||
dt
|
||||
border-color themeDarkBorder
|
||||
dd
|
||||
border-color themeDarkBorder
|
||||
background-color $ui-monokai-noteDetail-backgroundColor
|
||||
|
||||
pre.fence
|
||||
.gallery
|
||||
.carousel-main, .carousel-footer
|
||||
@@ -566,6 +621,15 @@ body[data-theme="dracula"]
|
||||
kbd
|
||||
background-color themeDarkBackground
|
||||
|
||||
dl
|
||||
border-color themeDarkBorder
|
||||
background-color themeDraculaTableHead
|
||||
dt
|
||||
border-color themeDarkBorder
|
||||
dd
|
||||
border-color themeDarkBorder
|
||||
background-color $ui-dracula-noteDetail-backgroundColor
|
||||
|
||||
pre.fence
|
||||
.gallery
|
||||
.carousel-main, .carousel-footer
|
||||
|
||||
@@ -48,8 +48,12 @@ const languages = [
|
||||
locale: 'pl'
|
||||
},
|
||||
{
|
||||
name: 'Portuguese',
|
||||
locale: 'pt'
|
||||
name: 'Portuguese (PT-BR)',
|
||||
locale: 'pt-BR'
|
||||
},
|
||||
{
|
||||
name: 'Portuguese (PT-PT)',
|
||||
locale: 'pt-PT'
|
||||
},
|
||||
{
|
||||
name: 'Russian',
|
||||
@@ -61,6 +65,9 @@ const languages = [
|
||||
}, {
|
||||
name: 'Turkish',
|
||||
locale: 'tr'
|
||||
}, {
|
||||
name: 'Thai',
|
||||
locale: 'th'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function findNoteTitle (value) {
|
||||
export function findNoteTitle (value, enableFrontMatterTitle, frontMatterTitleField = 'title') {
|
||||
const splitted = value.split('\n')
|
||||
let title = null
|
||||
let isInsideCodeBlock = false
|
||||
@@ -6,6 +6,11 @@ export function findNoteTitle (value) {
|
||||
if (splitted[0] === '---') {
|
||||
let line = 0
|
||||
while (++line < splitted.length) {
|
||||
if (enableFrontMatterTitle && splitted[line].startsWith(frontMatterTitleField + ':')) {
|
||||
title = splitted[line].substring(frontMatterTitleField.length + 1).trim()
|
||||
|
||||
break
|
||||
}
|
||||
if (splitted[line] === '---') {
|
||||
splitted.splice(0, line + 1)
|
||||
|
||||
@@ -14,17 +19,19 @@ export function findNoteTitle (value) {
|
||||
}
|
||||
}
|
||||
|
||||
splitted.some((line, index) => {
|
||||
const trimmedLine = line.trim()
|
||||
const trimmedNextLine = splitted[index + 1] === undefined ? '' : splitted[index + 1].trim()
|
||||
if (trimmedLine.match('```')) {
|
||||
isInsideCodeBlock = !isInsideCodeBlock
|
||||
}
|
||||
if (isInsideCodeBlock === false && (trimmedLine.match(/^# +/) || trimmedNextLine.match(/^=+$/))) {
|
||||
title = trimmedLine
|
||||
return true
|
||||
}
|
||||
})
|
||||
if (title === null) {
|
||||
splitted.some((line, index) => {
|
||||
const trimmedLine = line.trim()
|
||||
const trimmedNextLine = splitted[index + 1] === undefined ? '' : splitted[index + 1].trim()
|
||||
if (trimmedLine.match('```')) {
|
||||
isInsideCodeBlock = !isInsideCodeBlock
|
||||
}
|
||||
if (isInsideCodeBlock === false && (trimmedLine.match(/^# +/) || trimmedNextLine.match(/^=+$/))) {
|
||||
title = trimmedLine
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (title === null) {
|
||||
title = ''
|
||||
|
||||
232
browser/lib/markdown-it-deflist.js
Normal file
232
browser/lib/markdown-it-deflist.js
Normal file
@@ -0,0 +1,232 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = function definitionListPlugin (md) {
|
||||
var isSpace = md.utils.isSpace
|
||||
|
||||
// Search `[:~][\n ]`, returns next pos after marker on success
|
||||
// or -1 on fail.
|
||||
function skipMarker (state, line) {
|
||||
let start = state.bMarks[line] + state.tShift[line]
|
||||
const max = state.eMarks[line]
|
||||
|
||||
if (start >= max) { return -1 }
|
||||
|
||||
// Check bullet
|
||||
const marker = state.src.charCodeAt(start++)
|
||||
if (marker !== 0x7E/* ~ */ && marker !== 0x3A/* : */) { return -1 }
|
||||
|
||||
const pos = state.skipSpaces(start)
|
||||
|
||||
// require space after ":"
|
||||
if (start === pos) { return -1 }
|
||||
|
||||
return start
|
||||
}
|
||||
|
||||
function markTightParagraphs (state, idx) {
|
||||
const level = state.level + 2
|
||||
|
||||
let i
|
||||
let l
|
||||
for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {
|
||||
if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {
|
||||
state.tokens[i + 2].hidden = true
|
||||
state.tokens[i].hidden = true
|
||||
i += 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function deflist (state, startLine, endLine, silent) {
|
||||
var ch,
|
||||
contentStart,
|
||||
ddLine,
|
||||
dtLine,
|
||||
itemLines,
|
||||
listLines,
|
||||
listTokIdx,
|
||||
max,
|
||||
newEndLine,
|
||||
nextLine,
|
||||
offset,
|
||||
oldDDIndent,
|
||||
oldIndent,
|
||||
oldLineMax,
|
||||
oldParentType,
|
||||
oldSCount,
|
||||
oldTShift,
|
||||
oldTight,
|
||||
pos,
|
||||
prevEmptyEnd,
|
||||
tight,
|
||||
token
|
||||
|
||||
if (silent) {
|
||||
// quirk: validation mode validates a dd block only, not a whole deflist
|
||||
if (state.ddIndent < 0) { return false }
|
||||
return skipMarker(state, startLine) >= 0
|
||||
}
|
||||
|
||||
nextLine = startLine + 1
|
||||
if (nextLine >= endLine) { return false }
|
||||
|
||||
if (state.isEmpty(nextLine)) {
|
||||
nextLine++
|
||||
if (nextLine >= endLine) { return false }
|
||||
}
|
||||
|
||||
if (state.sCount[nextLine] < state.blkIndent) { return false }
|
||||
contentStart = skipMarker(state, nextLine)
|
||||
if (contentStart < 0) { return false }
|
||||
|
||||
// Start list
|
||||
listTokIdx = state.tokens.length
|
||||
tight = true
|
||||
|
||||
token = state.push('dl_open', 'dl', 1)
|
||||
token.map = listLines = [ startLine, 0 ]
|
||||
|
||||
//
|
||||
// Iterate list items
|
||||
//
|
||||
|
||||
dtLine = startLine
|
||||
ddLine = nextLine
|
||||
|
||||
// One definition list can contain multiple DTs,
|
||||
// and one DT can be followed by multiple DDs.
|
||||
//
|
||||
// Thus, there is two loops here, and label is
|
||||
// needed to break out of the second one
|
||||
//
|
||||
/* eslint no-labels:0,block-scoped-var:0 */
|
||||
OUTER:
|
||||
for (;;) {
|
||||
prevEmptyEnd = false
|
||||
|
||||
token = state.push('dt_open', 'dt', 1)
|
||||
token.map = [ dtLine, dtLine ]
|
||||
|
||||
token = state.push('inline', '', 0)
|
||||
token.map = [ dtLine, dtLine ]
|
||||
token.content = state.getLines(dtLine, dtLine + 1, state.blkIndent, false).trim()
|
||||
token.children = []
|
||||
|
||||
token = state.push('dt_close', 'dt', -1)
|
||||
|
||||
for (;;) {
|
||||
token = state.push('dd_open', 'dd', 1)
|
||||
token.map = itemLines = [ ddLine, 0 ]
|
||||
|
||||
pos = contentStart
|
||||
max = state.eMarks[ddLine]
|
||||
offset = state.sCount[ddLine] + contentStart - (state.bMarks[ddLine] + state.tShift[ddLine])
|
||||
|
||||
while (pos < max) {
|
||||
ch = state.src.charCodeAt(pos)
|
||||
|
||||
if (isSpace(ch)) {
|
||||
if (ch === 0x09) {
|
||||
offset += 4 - offset % 4
|
||||
} else {
|
||||
offset++
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
pos++
|
||||
}
|
||||
|
||||
contentStart = pos
|
||||
|
||||
oldTight = state.tight
|
||||
oldDDIndent = state.ddIndent
|
||||
oldIndent = state.blkIndent
|
||||
oldTShift = state.tShift[ddLine]
|
||||
oldSCount = state.sCount[ddLine]
|
||||
oldParentType = state.parentType
|
||||
state.blkIndent = state.ddIndent = state.sCount[ddLine] + 2
|
||||
state.tShift[ddLine] = contentStart - state.bMarks[ddLine]
|
||||
state.sCount[ddLine] = offset
|
||||
state.tight = true
|
||||
state.parentType = 'deflist'
|
||||
|
||||
newEndLine = ddLine
|
||||
while (++newEndLine < endLine && (state.sCount[newEndLine] >= state.sCount[ddLine] || state.isEmpty(newEndLine))) {
|
||||
}
|
||||
|
||||
oldLineMax = state.lineMax
|
||||
state.lineMax = newEndLine
|
||||
|
||||
state.md.block.tokenize(state, ddLine, newEndLine, true)
|
||||
|
||||
state.lineMax = oldLineMax
|
||||
|
||||
// If any of list item is tight, mark list as tight
|
||||
if (!state.tight || prevEmptyEnd) {
|
||||
tight = false
|
||||
}
|
||||
// Item become loose if finish with empty line,
|
||||
// but we should filter last element, because it means list finish
|
||||
prevEmptyEnd = (state.line - ddLine) > 1 && state.isEmpty(state.line - 1)
|
||||
|
||||
state.tShift[ddLine] = oldTShift
|
||||
state.sCount[ddLine] = oldSCount
|
||||
state.tight = oldTight
|
||||
state.parentType = oldParentType
|
||||
state.blkIndent = oldIndent
|
||||
state.ddIndent = oldDDIndent
|
||||
|
||||
token = state.push('dd_close', 'dd', -1)
|
||||
|
||||
itemLines[1] = nextLine = state.line
|
||||
|
||||
if (nextLine >= endLine) { break OUTER }
|
||||
|
||||
if (state.sCount[nextLine] < state.blkIndent) { break OUTER }
|
||||
contentStart = skipMarker(state, nextLine)
|
||||
if (contentStart < 0) { break }
|
||||
|
||||
ddLine = nextLine
|
||||
|
||||
// go to the next loop iteration:
|
||||
// insert DD tag and repeat checking
|
||||
}
|
||||
|
||||
if (nextLine >= endLine) { break }
|
||||
dtLine = nextLine
|
||||
|
||||
if (state.isEmpty(dtLine)) { break }
|
||||
if (state.sCount[dtLine] < state.blkIndent) { break }
|
||||
|
||||
ddLine = dtLine + 1
|
||||
if (ddLine >= endLine) { break }
|
||||
if (state.isEmpty(ddLine)) { ddLine++ }
|
||||
if (ddLine >= endLine) { break }
|
||||
|
||||
if (state.sCount[ddLine] < state.blkIndent) { break }
|
||||
contentStart = skipMarker(state, ddLine)
|
||||
if (contentStart < 0) { break }
|
||||
|
||||
// go to the next loop iteration:
|
||||
// insert DT and DD tags and repeat checking
|
||||
}
|
||||
|
||||
// Finilize list
|
||||
token = state.push('dl_close', 'dl', -1)
|
||||
|
||||
listLines[1] = nextLine
|
||||
|
||||
state.line = nextLine
|
||||
|
||||
// mark paragraphs tight if needed
|
||||
if (tight) {
|
||||
markTightParagraphs(state, listTokIdx)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
md.block.ruler.before('paragraph', 'deflist', deflist, { alt: [ 'paragraph', 'reference' ] })
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import sanitizeHtml from 'sanitize-html'
|
||||
import { escapeHtmlCharacters } from './utils'
|
||||
import url from 'url'
|
||||
|
||||
module.exports = function sanitizePlugin (md, options) {
|
||||
options = options || {}
|
||||
@@ -25,7 +26,7 @@ module.exports = function sanitizePlugin (md, options) {
|
||||
const inlineTokens = state.tokens[tokenIdx].children
|
||||
for (let childIdx = 0; childIdx < inlineTokens.length; childIdx++) {
|
||||
if (inlineTokens[childIdx].type === 'html_inline') {
|
||||
inlineTokens[childIdx].content = sanitizeHtml(
|
||||
inlineTokens[childIdx].content = sanitizeInline(
|
||||
inlineTokens[childIdx].content,
|
||||
options
|
||||
)
|
||||
@@ -35,3 +36,89 @@ module.exports = function sanitizePlugin (md, options) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const tagRegex = /<([A-Z][A-Z0-9]*)\s*((?:\s*[A-Z][A-Z0-9]*(?:=("|')(?:[^\3]+?)\3)?)*)\s*\/?>|<\/([A-Z][A-Z0-9]*)\s*>/i
|
||||
const attributesRegex = /([A-Z][A-Z0-9]*)(?:=("|')([^\2]+?)\2)?/ig
|
||||
|
||||
function sanitizeInline (html, options) {
|
||||
let match = tagRegex.exec(html)
|
||||
if (!match) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const { allowedTags, allowedAttributes, selfClosing, allowedSchemesAppliedToAttributes } = options
|
||||
|
||||
if (match[1] !== undefined) {
|
||||
// opening tag
|
||||
const tag = match[1].toLowerCase()
|
||||
if (allowedTags.indexOf(tag) === -1) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const attributes = match[2]
|
||||
|
||||
let attrs = ''
|
||||
let name
|
||||
let value
|
||||
|
||||
while ((match = attributesRegex.exec(attributes))) {
|
||||
name = match[1].toLowerCase()
|
||||
value = match[3]
|
||||
|
||||
if (allowedAttributes['*'].indexOf(name) !== -1 || (allowedAttributes[tag] && allowedAttributes[tag].indexOf(name) !== -1)) {
|
||||
if (allowedSchemesAppliedToAttributes.indexOf(name) !== -1) {
|
||||
if (naughtyHRef(value, options) || (tag === 'iframe' && name === 'src' && naughtyIFrame(value, options))) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
attrs += ` ${name}`
|
||||
if (match[2]) {
|
||||
attrs += `="${value}"`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selfClosing.indexOf(tag) === -1) {
|
||||
return '<' + tag + attrs + '>'
|
||||
} else {
|
||||
return '<' + tag + attrs + ' />'
|
||||
}
|
||||
} else {
|
||||
// closing tag
|
||||
if (allowedTags.indexOf(match[4].toLowerCase()) !== -1) {
|
||||
return html
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function naughtyHRef (href, options) {
|
||||
// href = href.replace(/[\x00-\x20]+/g, '')
|
||||
href = href.replace(/<\!\-\-.*?\-\-\>/g, '')
|
||||
|
||||
const matches = href.match(/^([a-zA-Z]+)\:/)
|
||||
if (!matches) {
|
||||
if (href.match(/^[\/\\]{2}/)) {
|
||||
return !options.allowProtocolRelative
|
||||
}
|
||||
|
||||
// No scheme
|
||||
return false
|
||||
}
|
||||
|
||||
const scheme = matches[1].toLowerCase()
|
||||
|
||||
return options.allowedSchemes.indexOf(scheme) === -1
|
||||
}
|
||||
|
||||
function naughtyIFrame (src, options) {
|
||||
try {
|
||||
const parsed = url.parse(src, false, true)
|
||||
|
||||
return options.allowedIframeHostnames.index(parsed.hostname) === -1
|
||||
} catch (e) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ function createGutter (str, firstLineNumber) {
|
||||
|
||||
class Markdown {
|
||||
constructor (options = {}) {
|
||||
let config = ConfigManager.get()
|
||||
const config = ConfigManager.get()
|
||||
const defaultOptions = {
|
||||
typographer: config.preview.smartQuotes,
|
||||
linkify: true,
|
||||
@@ -80,7 +80,11 @@ class Markdown {
|
||||
'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen'],
|
||||
'input': ['type', 'id', 'checked']
|
||||
},
|
||||
allowedIframeHostnames: ['www.youtube.com']
|
||||
allowedIframeHostnames: ['www.youtube.com'],
|
||||
selfClosing: [ 'img', 'br', 'hr', 'input' ],
|
||||
allowedSchemes: [ 'http', 'https', 'ftp', 'mailto' ],
|
||||
allowedSchemesAppliedToAttributes: [ 'href', 'src', 'cite' ],
|
||||
allowProtocolRelative: true
|
||||
})
|
||||
}
|
||||
|
||||
@@ -123,8 +127,11 @@ class Markdown {
|
||||
}
|
||||
})
|
||||
this.md.use(require('markdown-it-kbd'))
|
||||
|
||||
this.md.use(require('markdown-it-admonition'), {types: ['note', 'hint', 'attention', 'caution', 'danger', 'error']})
|
||||
this.md.use(require('markdown-it-abbr'))
|
||||
this.md.use(require('markdown-it-sub'))
|
||||
this.md.use(require('markdown-it-sup'))
|
||||
this.md.use(require('./markdown-it-deflist'))
|
||||
this.md.use(require('./markdown-it-frontmatter'))
|
||||
|
||||
this.md.use(require('./markdown-it-fence'), {
|
||||
@@ -279,9 +286,12 @@ class Markdown {
|
||||
this.md.renderer.render = (tokens, options, env) => {
|
||||
tokens.forEach((token) => {
|
||||
switch (token.type) {
|
||||
case 'heading_open':
|
||||
case 'paragraph_open':
|
||||
case 'blockquote_open':
|
||||
case 'dd_open':
|
||||
case 'dt_open':
|
||||
case 'heading_open':
|
||||
case 'list_item_open':
|
||||
case 'paragraph_open':
|
||||
case 'table_open':
|
||||
token.attrPush(['data-line', token.map[0]])
|
||||
}
|
||||
@@ -291,9 +301,6 @@ class Markdown {
|
||||
}
|
||||
// FIXME We should not depend on global variable.
|
||||
window.md = this.md
|
||||
this.updateConfig = () => {
|
||||
config = ConfigManager.get()
|
||||
}
|
||||
}
|
||||
|
||||
render (content) {
|
||||
|
||||
@@ -61,11 +61,14 @@ class MarkdownNoteDetail extends React.Component {
|
||||
const reversedType = this.state.editorType === 'SPLIT' ? 'EDITOR_PREVIEW' : 'SPLIT'
|
||||
this.handleSwitchMode(reversedType)
|
||||
})
|
||||
ee.on('hotkey:deletenote', this.handleDeleteNote.bind(this))
|
||||
ee.on('code:generate-toc', this.generateToc)
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.note.key !== this.props.note.key && !this.state.isMovingNote) {
|
||||
const isNewNote = nextProps.note.key !== this.props.note.key
|
||||
const hasDeletedTags = nextProps.note.tags.length < this.props.note.tags.length
|
||||
if (!this.state.isMovingNote && (isNewNote || hasDeletedTags)) {
|
||||
if (this.saveQueue != null) this.saveNow()
|
||||
this.setState({
|
||||
note: Object.assign({}, nextProps.note)
|
||||
@@ -91,7 +94,7 @@ class MarkdownNoteDetail extends React.Component {
|
||||
handleUpdateContent () {
|
||||
const { note } = this.state
|
||||
note.content = this.refs.content.value
|
||||
note.title = markdown.strip(striptags(findNoteTitle(note.content)))
|
||||
note.title = markdown.strip(striptags(findNoteTitle(note.content, this.props.config.editor.enableFrontMatterTitle, this.props.config.editor.frontMatterTitleField)))
|
||||
this.updateNote(note)
|
||||
}
|
||||
|
||||
@@ -293,9 +296,33 @@ class MarkdownNoteDetail extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
handleDeleteNote () {
|
||||
this.handleTrashButtonClick()
|
||||
}
|
||||
|
||||
handleClearTodo () {
|
||||
const { note } = this.state
|
||||
const splitted = note.content.split('\n')
|
||||
|
||||
const clearTodoContent = splitted.map((line) => {
|
||||
const trimmedLine = line.trim()
|
||||
if (trimmedLine.match(/\[x\]/i)) {
|
||||
return line.replace(/\[x\]/i, '[ ]')
|
||||
} else {
|
||||
return line
|
||||
}
|
||||
}).join('\n')
|
||||
|
||||
note.content = clearTodoContent
|
||||
this.refs.content.setValue(note.content)
|
||||
|
||||
this.updateNote(note)
|
||||
}
|
||||
|
||||
renderEditor () {
|
||||
const { config, ignorePreviewPointerEvents } = this.props
|
||||
const { note } = this.state
|
||||
|
||||
if (this.state.editorType === 'EDITOR_PREVIEW') {
|
||||
return <MarkdownEditor
|
||||
ref='content'
|
||||
@@ -321,7 +348,7 @@ class MarkdownNoteDetail extends React.Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { data, location } = this.props
|
||||
const { data, location, config } = this.props
|
||||
const { note, editorType } = this.state
|
||||
const storageKey = note.storage
|
||||
const folderKey = note.folder
|
||||
@@ -372,10 +399,12 @@ class MarkdownNoteDetail extends React.Component {
|
||||
<TagSelect
|
||||
ref='tags'
|
||||
value={this.state.note.tags}
|
||||
saveTagsAlphabetically={config.ui.saveTagsAlphabetically}
|
||||
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
||||
data={data}
|
||||
onChange={this.handleUpdateTag.bind(this)}
|
||||
/>
|
||||
<TodoListPercentage percentageOfTodo={getTodoPercentageOfCompleted(note.content)} />
|
||||
<TodoListPercentage onClearCheckboxClick={(e) => this.handleClearTodo(e)} percentageOfTodo={getTodoPercentageOfCompleted(note.content)} />
|
||||
</div>
|
||||
<div styleName='info-right'>
|
||||
<ToggleModeButton onClick={(e) => this.handleSwitchMode(e)} editorType={editorType} />
|
||||
|
||||
@@ -112,7 +112,7 @@ class SnippetNoteDetail extends React.Component {
|
||||
if (this.refs.tags) note.tags = this.refs.tags.value
|
||||
note.description = this.refs.description.value
|
||||
note.updatedAt = new Date()
|
||||
note.title = findNoteTitle(note.description)
|
||||
note.title = findNoteTitle(note.description, false)
|
||||
|
||||
this.setState({
|
||||
note
|
||||
@@ -354,12 +354,10 @@ class SnippetNoteDetail extends React.Component {
|
||||
this.refs['code-' + this.state.snippetIndex].reload()
|
||||
|
||||
if (this.visibleTabs.offsetWidth > this.allTabs.scrollWidth) {
|
||||
console.log('no need for arrows')
|
||||
this.moveTabBarBy(0)
|
||||
} else {
|
||||
const lastTab = this.allTabs.lastChild
|
||||
if (lastTab.offsetLeft + lastTab.offsetWidth < this.visibleTabs.offsetWidth) {
|
||||
console.log('need to scroll')
|
||||
const width = this.visibleTabs.offsetWidth
|
||||
const newLeft = lastTab.offsetLeft + lastTab.offsetWidth - width
|
||||
this.moveTabBarBy(newLeft > 0 ? -newLeft : 0)
|
||||
@@ -627,7 +625,6 @@ class SnippetNoteDetail extends React.Component {
|
||||
}
|
||||
|
||||
focusEditor () {
|
||||
console.log('code-' + this.state.snippetIndex)
|
||||
this.refs['code-' + this.state.snippetIndex].focus()
|
||||
}
|
||||
|
||||
@@ -759,6 +756,8 @@ class SnippetNoteDetail extends React.Component {
|
||||
<TagSelect
|
||||
ref='tags'
|
||||
value={this.state.note.tags}
|
||||
saveTagsAlphabetically={config.ui.saveTagsAlphabetically}
|
||||
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
||||
data={data}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
/>
|
||||
|
||||
@@ -179,10 +179,10 @@ class TagSelect extends React.Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { value, className } = this.props
|
||||
const { value, className, showTagsAlphabetically } = this.props
|
||||
|
||||
const tagList = _.isArray(value)
|
||||
? value.map((tag) => {
|
||||
? (showTagsAlphabetically ? _.sortBy(value) : value).map((tag) => {
|
||||
return (
|
||||
<span styleName='tag'
|
||||
key={tag}
|
||||
|
||||
@@ -80,7 +80,6 @@ class Main extends React.Component {
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
console.log(data)
|
||||
store.dispatch({
|
||||
type: 'ADD_STORAGE',
|
||||
storage: data.storage,
|
||||
@@ -297,7 +296,7 @@ class Main extends React.Component {
|
||||
onMouseUp={e => this.handleMouseUp(e)}
|
||||
>
|
||||
<SideNav
|
||||
{..._.pick(this.props, ['dispatch', 'data', 'config', 'location'])}
|
||||
{..._.pick(this.props, ['dispatch', 'data', 'config', 'params', 'location'])}
|
||||
width={this.state.navWidth}
|
||||
/>
|
||||
{!config.isSideNavFolded &&
|
||||
|
||||
@@ -56,7 +56,6 @@ class NoteList extends React.Component {
|
||||
super(props)
|
||||
|
||||
this.selectNextNoteHandler = () => {
|
||||
console.log('fired next')
|
||||
this.selectNextNote()
|
||||
}
|
||||
this.selectPriorNoteHandler = () => {
|
||||
@@ -616,7 +615,6 @@ class NoteList extends React.Component {
|
||||
.catch((err) => {
|
||||
console.error('Cannot Delete note: ' + err)
|
||||
})
|
||||
console.log('Notes were all deleted')
|
||||
} else {
|
||||
if (!confirmDeleteNote(confirmDeletion, false)) return
|
||||
|
||||
@@ -636,7 +634,6 @@ class NoteList extends React.Component {
|
||||
})
|
||||
})
|
||||
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('EDIT_NOTE')
|
||||
console.log('Notes went to trash')
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Notes could not go to trash: ' + err)
|
||||
@@ -996,6 +993,7 @@ class NoteList extends React.Component {
|
||||
folderName={this.getNoteFolder(note).name}
|
||||
storageName={this.getNoteStorage(note).name}
|
||||
viewType={viewType}
|
||||
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ import TagButton from './TagButton'
|
||||
import {SortableContainer} from 'react-sortable-hoc'
|
||||
import i18n from 'browser/lib/i18n'
|
||||
import context from 'browser/lib/context'
|
||||
import { remote } from 'electron'
|
||||
|
||||
function matchActiveTags (tags, activeTags) {
|
||||
return _.every(activeTags, v => tags.indexOf(v) >= 0)
|
||||
}
|
||||
|
||||
class SideNav extends React.Component {
|
||||
// TODO: should not use electron stuff v0.7
|
||||
@@ -30,6 +35,52 @@ class SideNav extends React.Component {
|
||||
EventEmitter.off('side:preferences', this.handleMenuButtonClick)
|
||||
}
|
||||
|
||||
deleteTag (tag) {
|
||||
const selectedButton = remote.dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||
ype: 'warning',
|
||||
message: i18n.__('Confirm tag deletion'),
|
||||
detail: i18n.__('This will permanently remove this tag.'),
|
||||
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
|
||||
})
|
||||
|
||||
if (selectedButton === 0) {
|
||||
const { data, dispatch, location, params } = this.props
|
||||
|
||||
const notes = data.noteMap
|
||||
.map(note => note)
|
||||
.filter(note => note.tags.indexOf(tag) !== -1)
|
||||
.map(note => {
|
||||
note = Object.assign({}, note)
|
||||
note.tags = note.tags.slice()
|
||||
|
||||
note.tags.splice(note.tags.indexOf(tag), 1)
|
||||
|
||||
return note
|
||||
})
|
||||
|
||||
Promise
|
||||
.all(notes.map(note => dataApi.updateNote(note.storage, note.key, note)))
|
||||
.then(updatedNotes => {
|
||||
updatedNotes.forEach(note => {
|
||||
dispatch({
|
||||
type: 'UPDATE_NOTE',
|
||||
note
|
||||
})
|
||||
})
|
||||
|
||||
if (location.pathname.match('/tags')) {
|
||||
const tags = params.tagname.split(' ')
|
||||
const index = tags.indexOf(tag)
|
||||
if (index !== -1) {
|
||||
tags.splice(index, 1)
|
||||
|
||||
this.context.router.push(`/tags/${tags.map(tag => encodeURIComponent(tag)).join(' ')}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleMenuButtonClick (e) {
|
||||
openModal(PreferencesModal)
|
||||
}
|
||||
@@ -44,6 +95,17 @@ class SideNav extends React.Component {
|
||||
router.push('/starred')
|
||||
}
|
||||
|
||||
handleTagContextMenu (e, tag) {
|
||||
const menu = []
|
||||
|
||||
menu.push({
|
||||
label: i18n.__('Delete Tag'),
|
||||
click: this.deleteTag.bind(this, tag)
|
||||
})
|
||||
|
||||
context.popup(menu)
|
||||
}
|
||||
|
||||
handleToggleButtonClick (e) {
|
||||
const { dispatch, config } = this.props
|
||||
|
||||
@@ -144,12 +206,20 @@ class SideNav extends React.Component {
|
||||
|
||||
tagListComponent () {
|
||||
const { data, location, config } = this.props
|
||||
const relatedTags = this.getRelatedTags(this.getActiveTags(location.pathname), data.noteMap)
|
||||
const activeTags = this.getActiveTags(location.pathname)
|
||||
const relatedTags = this.getRelatedTags(activeTags, data.noteMap)
|
||||
let tagList = _.sortBy(data.tagNoteMap.map(
|
||||
(tag, name) => ({ name, size: tag.size, related: relatedTags.has(name) })
|
||||
), ['name']).filter(
|
||||
).filter(
|
||||
tag => tag.size > 0
|
||||
)
|
||||
), ['name'])
|
||||
if (config.ui.enableLiveNoteCounts && activeTags.length !== 0) {
|
||||
const notesTags = data.noteMap.map(note => note.tags)
|
||||
tagList = tagList.map(tag => {
|
||||
tag.size = notesTags.filter(tags => tags.includes(tag.name) && matchActiveTags(tags, activeTags)).length
|
||||
return tag
|
||||
})
|
||||
}
|
||||
if (config.sortTagsBy === 'COUNTER') {
|
||||
tagList = _.sortBy(tagList, item => (0 - item.size))
|
||||
}
|
||||
@@ -165,6 +235,7 @@ class SideNav extends React.Component {
|
||||
name={tag.name}
|
||||
handleClickTagListItem={this.handleClickTagListItem.bind(this)}
|
||||
handleClickNarrowToTag={this.handleClickNarrowToTag.bind(this)}
|
||||
handleContextMenu={this.handleTagContextMenu.bind(this)}
|
||||
isActive={this.getTagActive(location.pathname, tag.name)}
|
||||
isRelated={tag.related}
|
||||
key={tag.name}
|
||||
@@ -247,7 +318,6 @@ class SideNav extends React.Component {
|
||||
.catch((err) => {
|
||||
console.error('Cannot Delete note: ' + err)
|
||||
})
|
||||
console.log('Trash emptied')
|
||||
}
|
||||
|
||||
handleFilterButtonContextMenu (event) {
|
||||
|
||||
@@ -45,7 +45,6 @@ function initAwsMobileAnalytics () {
|
||||
if (getSendEventCond()) return
|
||||
AWS.config.credentials.get((err) => {
|
||||
if (!err) {
|
||||
console.log('Cognito Identity ID: ' + AWS.config.credentials.identityId)
|
||||
recordDynamicCustomEvent('APP_STARTED')
|
||||
recordStaticCustomEvent()
|
||||
}
|
||||
@@ -58,7 +57,7 @@ function recordDynamicCustomEvent (type, options = {}) {
|
||||
mobileAnalyticsClient.recordEvent(type, options)
|
||||
} catch (analyticsError) {
|
||||
if (analyticsError instanceof ReferenceError) {
|
||||
console.log(analyticsError.name + ': ' + analyticsError.message)
|
||||
console.error(analyticsError.name + ': ' + analyticsError.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,7 +70,7 @@ function recordStaticCustomEvent () {
|
||||
})
|
||||
} catch (analyticsError) {
|
||||
if (analyticsError instanceof ReferenceError) {
|
||||
console.log(analyticsError.name + ': ' + analyticsError.message)
|
||||
console.error(analyticsError.name + ': ' + analyticsError.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ export const DEFAULT_CONFIG = {
|
||||
amaEnabled: true,
|
||||
hotkey: {
|
||||
toggleMain: OSX ? 'Command + Alt + L' : 'Super + Alt + E',
|
||||
toggleMode: OSX ? 'Command + Option + M' : 'Ctrl + M'
|
||||
toggleMode: OSX ? 'Command + Alt + M' : 'Ctrl + M',
|
||||
deleteNote: OSX ? 'Command + Shift + Backspace' : 'Ctrl + Shift + Backspace'
|
||||
},
|
||||
ui: {
|
||||
language: 'en',
|
||||
@@ -43,11 +44,14 @@ export const DEFAULT_CONFIG = {
|
||||
enableRulers: false,
|
||||
rulers: [80, 120],
|
||||
displayLineNumbers: true,
|
||||
switchPreview: 'BLUR', // Available value: RIGHTCLICK, BLUR
|
||||
switchPreview: 'BLUR', // 'BLUR', 'DBL_CLICK', 'RIGHTCLICK'
|
||||
delfaultStatus: 'PREVIEW', // 'PREVIEW', 'CODE'
|
||||
scrollPastEnd: false,
|
||||
type: 'SPLIT',
|
||||
type: 'SPLIT', // 'SPLIT', 'EDITOR_PREVIEW'
|
||||
fetchUrlTitle: true,
|
||||
enableTableEditor: false
|
||||
enableTableEditor: false,
|
||||
enableFrontMatterTitle: true,
|
||||
frontMatterTitleField: 'title'
|
||||
},
|
||||
preview: {
|
||||
fontSize: '14',
|
||||
@@ -60,6 +64,7 @@ export const DEFAULT_CONFIG = {
|
||||
latexBlockClose: '$$',
|
||||
plantUMLServerAddress: 'http://www.plantuml.com/plantuml',
|
||||
scrollPastEnd: false,
|
||||
scrollSync: true,
|
||||
smartQuotes: true,
|
||||
breaks: true,
|
||||
smartArrows: false,
|
||||
@@ -198,7 +203,7 @@ function rewriteHotkey (config) {
|
||||
const keys = [...Object.keys(config.hotkey)]
|
||||
keys.forEach(key => {
|
||||
config.hotkey[key] = config.hotkey[key].replace(/Cmd/g, 'Command')
|
||||
config.hotkey[key] = config.hotkey[key].replace(/Opt/g, 'Alt')
|
||||
config.hotkey[key] = config.hotkey[key].replace(/Opt\s/g, 'Option ')
|
||||
})
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -529,7 +529,6 @@ function handleAttachmentLinkPaste (storageKey, noteKey, linkText) {
|
||||
return modifiedLinkText
|
||||
})
|
||||
} else {
|
||||
console.log('One if the parameters was null -> Do nothing..')
|
||||
return Promise.resolve(linkText)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ function renameStorage (key, name) {
|
||||
cachedStorageList = JSON.parse(localStorage.getItem('storages'))
|
||||
if (!_.isArray(cachedStorageList)) throw new Error('invalid storages')
|
||||
} catch (err) {
|
||||
console.log('error got')
|
||||
console.error(err)
|
||||
return Promise.reject(err)
|
||||
}
|
||||
|
||||
@@ -31,13 +31,9 @@ function resolveStorageData (storageCache) {
|
||||
|
||||
const version = parseInt(storage.version, 10)
|
||||
if (version >= 1) {
|
||||
if (version > 1) {
|
||||
console.log('The repository version is newer than one of current app.')
|
||||
}
|
||||
return Promise.resolve(storage)
|
||||
}
|
||||
|
||||
console.log('Transform Legacy storage', storage.path)
|
||||
return migrateFromV6Storage(storage.path)
|
||||
.then(() => storage)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ function resolveStorageNotes (storage) {
|
||||
notePathList = sander.readdirSync(notesDirPath)
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
console.log(notesDirPath, ' doesn\'t exist.')
|
||||
console.error(notesDirPath, ' doesn\'t exist.')
|
||||
sander.mkdirSync(notesDirPath)
|
||||
} else {
|
||||
console.warn('Failed to find note dir', notesDirPath, err)
|
||||
|
||||
@@ -12,7 +12,6 @@ function toggleStorage (key, isOpen) {
|
||||
cachedStorageList = JSON.parse(localStorage.getItem('storages'))
|
||||
if (!_.isArray(cachedStorageList)) throw new Error('invalid storages')
|
||||
} catch (err) {
|
||||
console.log('error got')
|
||||
console.error(err)
|
||||
return Promise.reject(err)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ function once (name, listener) {
|
||||
}
|
||||
|
||||
function emit (name, ...args) {
|
||||
console.log(name)
|
||||
remote.getCurrentWindow().webContents.send(name, ...args)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,13 @@ nodeIpc.connectTo(
|
||||
path.join(app.getPath('userData'), 'boostnote.service'),
|
||||
function () {
|
||||
nodeIpc.of.node.on('error', function (err) {
|
||||
console.log(err)
|
||||
console.error(err)
|
||||
})
|
||||
nodeIpc.of.node.on('connect', function () {
|
||||
console.log('Connected successfully')
|
||||
ipcRenderer.send('config-renew', {config: ConfigManager.get()})
|
||||
})
|
||||
nodeIpc.of.node.on('disconnect', function () {
|
||||
console.log('disconnected')
|
||||
return
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
@@ -3,5 +3,8 @@ import ee from 'browser/main/lib/eventEmitter'
|
||||
module.exports = {
|
||||
'toggleMode': () => {
|
||||
ee.emit('topbar:togglemodebutton')
|
||||
},
|
||||
'deleteNote': () => {
|
||||
ee.emit('hotkey:deletenote')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,21 +23,29 @@ class Crowdfunding extends React.Component {
|
||||
return (
|
||||
<div styleName='root'>
|
||||
<div styleName='header'>{i18n.__('Crowdfunding')}</div>
|
||||
<p>{i18n.__('Dear Boostnote users,')}</p>
|
||||
<br />
|
||||
<p>{i18n.__('Thank you for using Boostnote!')}</p>
|
||||
<p>{i18n.__('Boostnote is used in about 200 different countries and regions by an awesome community of developers.')}</p>
|
||||
<br />
|
||||
<p>{i18n.__('To support our growing userbase, and satisfy community expectations,')}</p>
|
||||
<p>{i18n.__('we would like to invest more time and resources in this project.')}</p>
|
||||
<p>{i18n.__('We launched IssueHunt which is an issue-based crowdfunding / sourcing platform for open source projects.')}</p>
|
||||
<p>{i18n.__('Anyone can put a bounty on not only a bug but also on OSS feature requests listed on IssueHunt. Collected funds will be distributed to project owners and contributors.')}</p>
|
||||
<br />
|
||||
<p>{i18n.__('If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!')}</p>
|
||||
<p>{i18n.__('### Sustainable Open Source Ecosystem')}</p>
|
||||
<p>{i18n.__('We discussed about open-source ecosystem and IssueHunt concept with the Boostnote team repeatedly. We actually also discussed with Matz who father of Ruby.')}</p>
|
||||
<p>{i18n.__('The original reason why we made IssueHunt was to reward our contributors of Boostnote project. We’ve got tons of Github stars and hundred of contributors in two years.')}</p>
|
||||
<p>{i18n.__('We thought that it will be nice if we can pay reward for our contributors.')}</p>
|
||||
<br />
|
||||
<p>{i18n.__('Thanks,')}</p>
|
||||
<p>{i18n.__('### We believe Meritocracy')}</p>
|
||||
<p>{i18n.__('We think developers who has skill and did great things must be rewarded properly.')}</p>
|
||||
<p>{i18n.__('OSS projects are used in everywhere on the internet, but no matter how they great, most of owners of those projects need to have another job to sustain their living.')}</p>
|
||||
<p>{i18n.__('It sometimes looks like exploitation.')}</p>
|
||||
<p>{i18n.__('We’ve realized IssueHunt could enhance sustainability of open-source ecosystem.')}</p>
|
||||
<br />
|
||||
<p>{i18n.__('As same as issues of Boostnote are already funded on IssueHunt, your open-source projects can be also started funding from now.')}</p>
|
||||
<br />
|
||||
<p>{i18n.__('Thank you,')}</p>
|
||||
<p>{i18n.__('The Boostnote Team')}</p>
|
||||
<br />
|
||||
<button styleName='cf-link'>
|
||||
<a href='https://opencollective.com/boostnoteio' onClick={(e) => this.handleLinkClick(e)}>{i18n.__('Support via OpenCollective')}</a>
|
||||
<a href='http://bit.ly/issuehunt-from-boostnote-app' onClick={(e) => this.handleLinkClick(e)}>{i18n.__('See IssueHunt')}</a>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -28,10 +28,20 @@ class HotkeyTab extends React.Component {
|
||||
}})
|
||||
}
|
||||
this.handleSettingError = (err) => {
|
||||
this.setState({keymapAlert: {
|
||||
type: 'error',
|
||||
message: err.message != null ? err.message : i18n.__('An error occurred!')
|
||||
}})
|
||||
if (
|
||||
this.state.config.hotkey.toggleMain === '' ||
|
||||
this.state.config.hotkey.toggleMode === ''
|
||||
) {
|
||||
this.setState({keymapAlert: {
|
||||
type: 'success',
|
||||
message: i18n.__('Successfully applied!')
|
||||
}})
|
||||
} else {
|
||||
this.setState({keymapAlert: {
|
||||
type: 'error',
|
||||
message: err.message != null ? err.message : i18n.__('An error occurred!')
|
||||
}})
|
||||
}
|
||||
}
|
||||
this.oldHotkey = this.state.config.hotkey
|
||||
ipc.addListener('APP_SETTING_DONE', this.handleSettingDone)
|
||||
@@ -68,7 +78,8 @@ class HotkeyTab extends React.Component {
|
||||
const { config } = this.state
|
||||
config.hotkey = {
|
||||
toggleMain: this.refs.toggleMain.value,
|
||||
toggleMode: this.refs.toggleMode.value
|
||||
toggleMode: this.refs.toggleMode.value,
|
||||
deleteNote: this.refs.deleteNote.value
|
||||
}
|
||||
this.setState({
|
||||
config
|
||||
@@ -127,6 +138,17 @@ class HotkeyTab extends React.Component {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label'>{i18n.__('Delete Note')}</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input styleName='group-section-control-input'
|
||||
onChange={(e) => this.handleHotkeyChange(e)}
|
||||
ref='deleteNote'
|
||||
value={config.hotkey.deleteNote}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div styleName='group-control'>
|
||||
<button styleName='group-control-leftButton'
|
||||
onClick={(e) => this.handleHintToggleButtonClick(e)}
|
||||
|
||||
@@ -84,7 +84,7 @@ class InfoTab extends React.Component {
|
||||
>{i18n.__('GitHub')}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href='https://boostlog.io/@junp1234'
|
||||
<a href='https://medium.com/boostnote'
|
||||
onClick={(e) => this.handleLinkClick(e)}
|
||||
>{i18n.__('Blog')}</a>
|
||||
</li>
|
||||
|
||||
@@ -71,6 +71,9 @@ class UiTab extends React.Component {
|
||||
showCopyNotification: this.refs.showCopyNotification.checked,
|
||||
confirmDeletion: this.refs.confirmDeletion.checked,
|
||||
showOnlyRelatedTags: this.refs.showOnlyRelatedTags.checked,
|
||||
showTagsAlphabetically: this.refs.showTagsAlphabetically.checked,
|
||||
saveTagsAlphabetically: this.refs.saveTagsAlphabetically.checked,
|
||||
enableLiveNoteCounts: this.refs.enableLiveNoteCounts.checked,
|
||||
disableDirectWrite: this.refs.uiD2w != null
|
||||
? this.refs.uiD2w.checked
|
||||
: false
|
||||
@@ -89,7 +92,9 @@ class UiTab extends React.Component {
|
||||
snippetDefaultLanguage: this.refs.editorSnippetDefaultLanguage.value,
|
||||
scrollPastEnd: this.refs.scrollPastEnd.checked,
|
||||
fetchUrlTitle: this.refs.editorFetchUrlTitle.checked,
|
||||
enableTableEditor: this.refs.enableTableEditor.checked
|
||||
enableTableEditor: this.refs.enableTableEditor.checked,
|
||||
enableFrontMatterTitle: this.refs.enableFrontMatterTitle.checked,
|
||||
frontMatterTitleField: this.refs.frontMatterTitleField.value
|
||||
},
|
||||
preview: {
|
||||
fontSize: this.refs.previewFontSize.value,
|
||||
@@ -102,6 +107,7 @@ class UiTab extends React.Component {
|
||||
latexBlockClose: this.refs.previewLatexBlockClose.value,
|
||||
plantUMLServerAddress: this.refs.previewPlantUMLServerAddress.value,
|
||||
scrollPastEnd: this.refs.previewScrollPastEnd.checked,
|
||||
scrollSync: this.refs.previewScrollSync.checked,
|
||||
smartQuotes: this.refs.previewSmartQuotes.checked,
|
||||
breaks: this.refs.previewBreaks.checked,
|
||||
smartArrows: this.refs.previewSmartArrows.checked,
|
||||
@@ -246,16 +252,6 @@ class UiTab extends React.Component {
|
||||
{i18n.__('Show a confirmation dialog when deleting notes')}
|
||||
</label>
|
||||
</div>
|
||||
<div styleName='group-checkBoxSection'>
|
||||
<label>
|
||||
<input onChange={(e) => this.handleUIChange(e)}
|
||||
checked={this.state.config.ui.showOnlyRelatedTags}
|
||||
ref='showOnlyRelatedTags'
|
||||
type='checkbox'
|
||||
/>
|
||||
{i18n.__('Show only related tags')}
|
||||
</label>
|
||||
</div>
|
||||
{
|
||||
global.process.platform === 'win32'
|
||||
? <div styleName='group-checkBoxSection'>
|
||||
@@ -271,6 +267,52 @@ class UiTab extends React.Component {
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
<div styleName='group-header2'>Tags</div>
|
||||
|
||||
<div styleName='group-checkBoxSection'>
|
||||
<label>
|
||||
<input onChange={(e) => this.handleUIChange(e)}
|
||||
checked={this.state.config.ui.saveTagsAlphabetically}
|
||||
ref='saveTagsAlphabetically'
|
||||
type='checkbox'
|
||||
/>
|
||||
{i18n.__('Save tags of a note in alphabetical order')}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div styleName='group-checkBoxSection'>
|
||||
<label>
|
||||
<input onChange={(e) => this.handleUIChange(e)}
|
||||
checked={this.state.config.ui.showTagsAlphabetically}
|
||||
ref='showTagsAlphabetically'
|
||||
type='checkbox'
|
||||
/>
|
||||
{i18n.__('Show tags of a note in alphabetical order')}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div styleName='group-checkBoxSection'>
|
||||
<label>
|
||||
<input onChange={(e) => this.handleUIChange(e)}
|
||||
checked={this.state.config.ui.showOnlyRelatedTags}
|
||||
ref='showOnlyRelatedTags'
|
||||
type='checkbox'
|
||||
/>
|
||||
{i18n.__('Show only related tags')}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div styleName='group-checkBoxSection'>
|
||||
<label>
|
||||
<input onChange={(e) => this.handleUIChange(e)}
|
||||
checked={this.state.config.ui.enableLiveNoteCounts}
|
||||
ref='enableLiveNoteCounts'
|
||||
type='checkbox'
|
||||
/>
|
||||
{i18n.__('Enable live count of notes')}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div styleName='group-header2'>Editor</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
@@ -428,6 +470,31 @@ class UiTab extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label'>
|
||||
{i18n.__('Front matter title field')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input styleName='group-section-control-input'
|
||||
ref='frontMatterTitleField'
|
||||
value={config.editor.frontMatterTitleField}
|
||||
onChange={(e) => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-checkBoxSection'>
|
||||
<label>
|
||||
<input onChange={(e) => this.handleUIChange(e)}
|
||||
checked={this.state.config.editor.enableFrontMatterTitle}
|
||||
ref='enableFrontMatterTitle'
|
||||
type='checkbox'
|
||||
/>
|
||||
{i18n.__('Extract title from front matter')}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div styleName='group-checkBoxSection'>
|
||||
<label>
|
||||
<input onChange={(e) => this.handleUIChange(e)}
|
||||
@@ -534,6 +601,16 @@ class UiTab extends React.Component {
|
||||
{i18n.__('Allow preview to scroll past the last line')}
|
||||
</label>
|
||||
</div>
|
||||
<div styleName='group-checkBoxSection'>
|
||||
<label>
|
||||
<input onChange={(e) => this.handleUIChange(e)}
|
||||
checked={this.state.config.preview.scrollSync}
|
||||
ref='previewScrollSync'
|
||||
type='checkbox'
|
||||
/>
|
||||
{i18n.__('When scrolling, synchronize preview with editor')}
|
||||
</label>
|
||||
</div>
|
||||
<div styleName='group-checkBoxSection'>
|
||||
<label>
|
||||
<input onChange={(e) => this.handleUIChange(e)}
|
||||
|
||||
@@ -113,7 +113,6 @@ function data (state = defaultDataMap(), action) {
|
||||
|
||||
// If storage chanced, origin key must be discarded
|
||||
if (originKey !== uniqueKey) {
|
||||
console.log('diffrent storage')
|
||||
// From isStarred
|
||||
if (originNote.isStarred) {
|
||||
state.starredSet = new Set(state.starredSet)
|
||||
|
||||
@@ -49,7 +49,7 @@ function startServer () {
|
||||
}
|
||||
|
||||
function startElectron () {
|
||||
spawn(electron, ['--hot', './index.js'])
|
||||
spawn(electron, ['--hot', './index.js'], { stdio: 'inherit' })
|
||||
.on('close', () => {
|
||||
server.close()
|
||||
})
|
||||
|
||||
@@ -52,7 +52,10 @@
|
||||
|
||||
if (className.indexOf('cm-url') !== -1) {
|
||||
const match = /^\((.*)\)|\[(.*)\]|(.*)$/.exec(el.textContent)
|
||||
return match[1] || match[2] || match[3]
|
||||
const url = match[1] || match[2] || match[3]
|
||||
|
||||
// `:storage` is the value of the variable `STORAGE_FOLDER_PLACEHOLDER` defined in `browser/main/lib/dataApi/attachmentManagement`
|
||||
return /^:storage(?:\/|%5C)/.test(url) ? null : url
|
||||
}
|
||||
|
||||
return null
|
||||
|
||||
3
extra_scripts/codemirror/mode/bfm/bfm.css
vendored
3
extra_scripts/codemirror/mode/bfm/bfm.css
vendored
@@ -34,7 +34,6 @@
|
||||
.cm-s-rubyblue.CodeMirror .cm-table-row-even { background-color: rgb(41, 58, 73); }
|
||||
.cm-s-seti.CodeMirror .cm-table-row-even { background-color: rgb(40, 42, 43); }
|
||||
.cm-s-shadowfox.CodeMirror .cm-table-row-even { background-color: rgb(56, 56, 59); }
|
||||
.cm-s-solarized.CodeMirror .cm-table-row-even { background-color: rgb(242, 242, 242); }
|
||||
.cm-s-the-matrix.CodeMirror .cm-table-row-even { background-color: rgb(0, 26, 0); }
|
||||
.cm-s-tomorrow-night-bright.CodeMirror .cm-table-row-even { background-color: rgb(23, 23, 23); }
|
||||
.cm-s-tomorrow-night-eighties.CodeMirror .cm-table-row-even { background-color: rgb(20, 20, 20); }
|
||||
@@ -42,3 +41,5 @@
|
||||
.cm-s-vibrant-ink.CodeMirror .cm-table-row-even { background-color: rgb(26, 26, 26); }
|
||||
.cm-s-xq-dark.CodeMirror .cm-table-row-even { background-color: rgb(34, 25, 53); }
|
||||
.cm-s-yeti.CodeMirror .cm-table-row-even { background-color: rgb(235, 232, 230); }
|
||||
.cm-s-solarized.cm-s-dark .cm-table-row-even { background-color: rgb(13, 54, 64); }
|
||||
.cm-s-solarized.cm-s-light .cm-table-row-even { background-color: rgb(245, 240, 222); }
|
||||
5
extra_scripts/codemirror/mode/bfm/bfm.js
vendored
5
extra_scripts/codemirror/mode/bfm/bfm.js
vendored
@@ -194,7 +194,8 @@
|
||||
return 'table table-header'
|
||||
}
|
||||
|
||||
stream.next()
|
||||
stream.skipToEnd()
|
||||
return null
|
||||
},
|
||||
electricChars: baseMode.electricChars,
|
||||
innerMode: function(state) {
|
||||
@@ -211,6 +212,8 @@
|
||||
}
|
||||
},
|
||||
blankLine: function(state) {
|
||||
state.inTable = false
|
||||
|
||||
if (state.fencedMode) {
|
||||
return state.fencedMode.blankLine && state.fencedMode.blankLine(state.fencedState)
|
||||
} else {
|
||||
|
||||
33
gruntfile.js
33
gruntfile.js
@@ -289,9 +289,23 @@ module.exports = function (grunt) {
|
||||
const Color = require('color')
|
||||
const parseCSS = require('css').parse
|
||||
|
||||
function generateRule (selector, bgColor, fgColor) {
|
||||
if (bgColor.isLight()) {
|
||||
bgColor = bgColor.mix(fgColor, 0.05)
|
||||
} else {
|
||||
bgColor = bgColor.mix(fgColor, 0.1)
|
||||
}
|
||||
|
||||
if (selector && selector.length > 0) {
|
||||
return `${selector} .cm-table-row-even { background-color: ${bgColor.rgb().string()}; }`
|
||||
} else {
|
||||
return `.cm-table-row-even { background-color: ${bgColor.rgb().string()}; }`
|
||||
}
|
||||
}
|
||||
|
||||
const root = path.join(__dirname, 'node_modules/codemirror/theme/')
|
||||
|
||||
const colors = fs.readdirSync(root).map(file => {
|
||||
const colors = fs.readdirSync(root).filter(file => file !== 'solarized.css').map(file => {
|
||||
const css = parseCSS(fs.readFileSync(path.join(root, file), 'utf8'))
|
||||
|
||||
const rules = css.stylesheet.rules.filter(rule => rule.selectors && /\b\.CodeMirror$/.test(rule.selectors[0]))
|
||||
@@ -313,19 +327,18 @@ module.exports = function (grunt) {
|
||||
}
|
||||
})
|
||||
|
||||
if (bgColor.isLight()) {
|
||||
bgColor = bgColor.mix(fgColor, 0.05)
|
||||
} else {
|
||||
bgColor = bgColor.mix(fgColor, 0.1)
|
||||
}
|
||||
|
||||
return `${rules[0].selectors[0]} .cm-table-row-even { background-color: ${bgColor.rgb().string()}; }`
|
||||
return generateRule(rules[0].selectors[0], bgColor, fgColor)
|
||||
}
|
||||
}).filter(value => !!value)
|
||||
|
||||
const defaultBgColor = Color('white').mix(Color('black'), 0.05)
|
||||
// default
|
||||
colors.unshift(generateRule(null, Color('white'), Color('black')))
|
||||
// solarized dark
|
||||
colors.push(generateRule('.cm-s-solarized.cm-s-dark', Color('#002b36'), Color('#839496')))
|
||||
// solarized light
|
||||
colors.push(generateRule('.cm-s-solarized.cm-s-light', Color('#fdf6e3'), Color('#657b83')))
|
||||
|
||||
fs.writeFileSync(path.join(__dirname, 'extra_scripts/codemirror/mode/bfm/bfm.css'), [`.cm-table-row-even { background-color: ${defaultBgColor.rgb().string()}; }`, ...colors].join('\n'), 'utf8')
|
||||
fs.writeFileSync(path.join(__dirname, 'extra_scripts/codemirror/mode/bfm/bfm.css'), colors.join('\n'), 'utf8')
|
||||
})
|
||||
|
||||
grunt.registerTask('default', ['build'])
|
||||
|
||||
@@ -59,7 +59,7 @@ updater.on('update-downloaded', (info) => {
|
||||
})
|
||||
|
||||
updater.autoUpdater.on('error', (err) => {
|
||||
console.log(err)
|
||||
console.error(err)
|
||||
})
|
||||
|
||||
ipc.on('update-app-confirm', function (event, msg) {
|
||||
|
||||
@@ -7,13 +7,19 @@ const config = new Config()
|
||||
const _ = require('lodash')
|
||||
|
||||
var showMenu = process.platform !== 'win32'
|
||||
const windowSize = config.get('windowsize') || { x: null, y: null, width: 1080, height: 720 }
|
||||
const windowSize = config.get('windowsize') || {
|
||||
x: null,
|
||||
y: null,
|
||||
width: 1080,
|
||||
height: 720
|
||||
}
|
||||
|
||||
const mainWindow = new BrowserWindow({
|
||||
x: windowSize.x,
|
||||
y: windowSize.y,
|
||||
width: windowSize.width,
|
||||
height: windowSize.height,
|
||||
useContentSize: true,
|
||||
minWidth: 500,
|
||||
minHeight: 320,
|
||||
autoHideMenuBar: showMenu,
|
||||
|
||||
@@ -145,6 +145,7 @@
|
||||
"UserName": "Benutzername",
|
||||
"Password": "Passwort",
|
||||
"Russian": "Russisch",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Command(⌘)": "Befehlstaste(⌘)",
|
||||
"Editor Rulers": "Editor Trennline",
|
||||
"Enable": "Aktiviert",
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
"The Boostnote Team": "The Boostnote Team",
|
||||
"Support via OpenCollective": "Support via OpenCollective",
|
||||
"Language": "Language",
|
||||
"Default New Note": "Default New Note",
|
||||
"English": "English",
|
||||
"German": "German",
|
||||
"French": "French",
|
||||
@@ -135,6 +136,7 @@
|
||||
"Hotkeys": "Hotkeys",
|
||||
"Show/Hide Boostnote": "Show/Hide Boostnote",
|
||||
"Toggle Editor Mode": "Toggle Editor Mode",
|
||||
"Delete Note": "Delete Note",
|
||||
"Restore": "Restore",
|
||||
"Permanent Delete": "Permanent Delete",
|
||||
"Confirm note deletion": "Confirm note deletion",
|
||||
@@ -155,6 +157,7 @@
|
||||
"Password": "Password",
|
||||
"Russian": "Russian",
|
||||
"Hungarian": "Hungarian",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Command(⌘)": "Command(⌘)",
|
||||
"Add Storage": "Add Storage",
|
||||
"Name": "Name",
|
||||
@@ -176,6 +179,9 @@
|
||||
"Allow dangerous html tags": "Allow dangerous html tags",
|
||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠",
|
||||
"Save tags of a note in alphabetical order": "Save tags of a note in alphabetical order",
|
||||
"Show tags of a note in alphabetical order": "Show tags of a note in alphabetical order",
|
||||
"Enable live count of notes": "Enable live count of notes",
|
||||
"Enable smart table editor": "Enable smart table editor",
|
||||
"Snippet Default Language": "Snippet Default Language"
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"Spanish": "Español",
|
||||
"Unsaved Changes!": "¡Tienes que guardar!",
|
||||
"Russian": "Ruso",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Command(⌘)": "Comando(⌘)",
|
||||
"Editor Rulers": "Reglas del editor",
|
||||
"Enable": "Activar",
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
"UserName": "نام کاربری",
|
||||
"Password": "رمز عبور",
|
||||
"Russian": "روسی",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Command(⌘)": "Command(⌘)",
|
||||
"Editor Rulers": "Editor Rulers",
|
||||
"Enable": "فعال",
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"Editor Indent Style": "Style d'indentation de l'éditeur",
|
||||
"Spaces": "Espaces",
|
||||
"Tabs": "Tabulations",
|
||||
"Show only related tags": "Afficher uniquement les tags associés",
|
||||
"Switch to Preview": "Switcher vers l'aperçu",
|
||||
"When Editor Blurred": "Quand l'éditeur n'est pas sélectionné",
|
||||
"When Editor Blurred, Edit On Double Click": "Quand l'éditeur n'est pas sélectionné, éditer avec un double clic",
|
||||
@@ -57,6 +58,7 @@
|
||||
"Preview Font Family": "Police de l'aperçu",
|
||||
"Code Block Theme": "Thème des blocs de code",
|
||||
"Show line numbers for preview code blocks": "Montrer les numéros de lignes dans les blocs de code dans l'aperçu",
|
||||
"Enable smart quotes": "Activer les citations intelligentes",
|
||||
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
|
||||
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
||||
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
||||
@@ -92,6 +94,7 @@
|
||||
"The Boostnote Team": "Les mainteneurs de Boostnote",
|
||||
"Support via OpenCollective": "Support via OpenCollective",
|
||||
"Language": "Langues",
|
||||
"Default New Note": "Nouvelle note par défaut",
|
||||
"English": "Anglais",
|
||||
"German": "Allemand",
|
||||
"French": "Français",
|
||||
@@ -114,8 +117,8 @@
|
||||
"Default View": "Vue par défaut",
|
||||
"Compressed View": "Vue compressée",
|
||||
"Search": "Chercher",
|
||||
"Blog Type": "Blog Type",
|
||||
"Blog Address": "Blog Address",
|
||||
"Blog Type": "Type du blog",
|
||||
"Blog Address": "Adresse du blog",
|
||||
"Save": "Sauvegarder",
|
||||
"Auth": "Auth",
|
||||
"Authentication Method": "Méthode d'Authentification",
|
||||
@@ -133,6 +136,7 @@
|
||||
"Albanian": "Albanais",
|
||||
"Chinese (zh-CN)": "Chinois (zh-CN)",
|
||||
"Chinese (zh-TW)": "Chinois (zh-TW)",
|
||||
"Toggle Editor Mode": "Basculer en mode éditeur",
|
||||
"Danish": "Danois",
|
||||
"Japanese": "Japonais",
|
||||
"Korean": "Coréen",
|
||||
@@ -142,6 +146,7 @@
|
||||
"Spanish": "Espagnol",
|
||||
"Unsaved Changes!": "Il faut sauvegarder !",
|
||||
"Russian": "Russe",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Command(⌘)": "Command(⌘)",
|
||||
"Editor Rulers": "Règles dans l'éditeur",
|
||||
"Enable": "Activer",
|
||||
@@ -153,6 +158,14 @@
|
||||
"Allow dangerous html tags": "Accepter les tags html dangereux",
|
||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convertir des flèches textuelles en jolis signes. ⚠ Cela va interferérer avec les éventuels commentaires HTML dans votre Markdown.",
|
||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ Vous avez collé un lien qui référence une pièce-jointe qui n'a pas pu être récupéré dans le dossier de stockage de la note. Coller des liens qui font référence à des pièces-jointes ne fonctionne que si la source et la destination et la même. Veuillez plutôt utiliser du Drag & Drop ! ⚠",
|
||||
"Save tags of a note in alphabetical order": "Sauvegarder les tags d'une note en ordre alphabétique",
|
||||
"Show tags of a note in alphabetical order": "Afficher les tags d'une note par ordre alphabétique",
|
||||
"Enable live count of notes": "Activer le comptage live des notes",
|
||||
"Enable smart table editor": "Activer l'intelligent éditeur de tableaux",
|
||||
"Snippet Default Language": "Langage par défaut d'un snippet"
|
||||
"Snippet Default Language": "Langage par défaut d'un snippet",
|
||||
"New Snippet": "Nouveau snippet",
|
||||
"Custom CSS": "CSS personnalisé",
|
||||
"Snippet name": "Nom du snippet",
|
||||
"Snippet prefix": "Préfixe du snippet"
|
||||
"Delete Note": "Supprimer la note"
|
||||
}
|
||||
|
||||
@@ -155,6 +155,7 @@
|
||||
"Password": "Jelszo",
|
||||
"Russian": "Russian",
|
||||
"Hungarian": "Hungarian",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Command(⌘)": "Command(⌘)",
|
||||
"Add Storage": "Tároló hozzáadása",
|
||||
"Name": "Név",
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
"UserName": "UserName",
|
||||
"Password": "Password",
|
||||
"Russian": "Russo",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Command(⌘)": "Comando(⌘)",
|
||||
"Editor Rulers": "Regole dell'editor",
|
||||
"Enable": "Abilita",
|
||||
|
||||
@@ -155,6 +155,7 @@
|
||||
"Password": "パスワード",
|
||||
"Russian": "ロシア語",
|
||||
"Hungarian": "ハンガリー語",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Command(⌘)": "コマンド(⌘)",
|
||||
"Add Storage": "ストレージを追加",
|
||||
"Name": "名前",
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"Spanish": "Spanish",
|
||||
"Unsaved Changes!": "저장해주세요!",
|
||||
"Russian": "Russian",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Command(⌘)": "Command(⌘)",
|
||||
"Delete Folder": "폴더 삭제",
|
||||
"This will delete all notes in the folder and can not be undone.": "폴더의 모든 노트를 지우게 되고, 되돌릴 수 없습니다.",
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"Spanish": "Spanish",
|
||||
"Unsaved Changes!": "Unsaved Changes!",
|
||||
"Russian": "Russian",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Editor Rulers": "Editor Rulers",
|
||||
"Enable": "Enable",
|
||||
"Disable": "Disable",
|
||||
|
||||
@@ -149,6 +149,7 @@
|
||||
"Spanish": "Hiszpański",
|
||||
"Unsaved Changes!": "Musisz zapisać!",
|
||||
"Russian": "Rosyjski",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Editor Rulers": "Margines",
|
||||
"Enable": "Włącz",
|
||||
"Disable": "Wyłącz",
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"Spanish": "Espanhol",
|
||||
"Unsaved Changes!": "Você precisa salvar!",
|
||||
"Russian": "Russo",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Editor Rulers": "Réguas do Editor",
|
||||
"Enable": "Habilitado",
|
||||
"Disable": "Desabilitado",
|
||||
|
||||
@@ -1,155 +1,155 @@
|
||||
{
|
||||
"Notes": "Notes",
|
||||
"Tags": "Tags",
|
||||
"Preferences": "Preferences",
|
||||
"Make a note": "Make a note",
|
||||
"Notes": "Notas",
|
||||
"Tags": "Etiquetas",
|
||||
"Preferences": "Definiçōes",
|
||||
"Make a note": "Criar nota",
|
||||
"Ctrl": "Ctrl",
|
||||
"Ctrl(^)": "Ctrl",
|
||||
"to create a new note": "to create a new note",
|
||||
"Toggle Mode": "Toggle Mode",
|
||||
"Trash": "Trash",
|
||||
"MODIFICATION DATE": "MODIFICATION DATE",
|
||||
"Words": "Words",
|
||||
"Letters": "Letters",
|
||||
"STORAGE": "STORAGE",
|
||||
"FOLDER": "FOLDER",
|
||||
"CREATION DATE": "CREATION DATE",
|
||||
"NOTE LINK": "NOTE LINK",
|
||||
"to create a new note": "para criar uma nova nota",
|
||||
"Toggle Mode": "Alternar Modo",
|
||||
"Trash": "Lixo",
|
||||
"MODIFICATION DATE": "DATA DE MODIFICAÇÃO",
|
||||
"Words": "Palavras",
|
||||
"Letters": "Letras",
|
||||
"STORAGE": "ARMAZENAMENTO",
|
||||
"FOLDER": "PASTA",
|
||||
"CREATION DATE": "DATA DE CRIAÇÃO",
|
||||
"NOTE LINK": "ATALHO DE NOTA",
|
||||
".md": ".md",
|
||||
".txt": ".txt",
|
||||
".html": ".html",
|
||||
"Print": "Print",
|
||||
"Your preferences for Boostnote": "Your preferences for Boostnote",
|
||||
"Storage Locations": "Storage Locations",
|
||||
"Add Storage Location": "Add Storage Location",
|
||||
"Add Folder": "Add Folder",
|
||||
"Open Storage folder": "Open Storage folder",
|
||||
"Unlink": "Unlink",
|
||||
"Edit": "Edit",
|
||||
"Delete": "Delete",
|
||||
"Print": "Imprimir",
|
||||
"Your preferences for Boostnote": "As tuas definiçōes para Boostnote",
|
||||
"Storage Locations": "Locais de Armazenamento",
|
||||
"Add Storage Location": "Adicionar Local de Armazenamento",
|
||||
"Add Folder": "Adicionar Pasta",
|
||||
"Open Storage folder": "Abrir Local de Armazenamento",
|
||||
"Unlink": "Remover a ligação",
|
||||
"Edit": "Editar",
|
||||
"Delete": "Apagar",
|
||||
"Interface": "Interface",
|
||||
"Interface Theme": "Interface Theme",
|
||||
"Interface Theme": "Tema",
|
||||
"Default": "Default",
|
||||
"White": "White",
|
||||
"White": "Branco",
|
||||
"Solarized Dark": "Solarized Dark",
|
||||
"Dark": "Dark",
|
||||
"Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes",
|
||||
"Editor Theme": "Editor Theme",
|
||||
"Editor Font Size": "Editor Font Size",
|
||||
"Editor Font Family": "Editor Font Family",
|
||||
"Editor Indent Style": "Editor Indent Style",
|
||||
"Spaces": "Spaces",
|
||||
"Dark": "Escuro",
|
||||
"Show a confirmation dialog when deleting notes": "Mostrar uma confirmação ao excluir notas",
|
||||
"Editor Theme": "Tema do Editor",
|
||||
"Editor Font Size": "Tamanho de Fonte do Editor",
|
||||
"Editor Font Family": "Família de Fonte do Editor",
|
||||
"Editor Indent Style": "Estílo de Identação do Editor",
|
||||
"Spaces": "Espaços",
|
||||
"Tabs": "Tabs",
|
||||
"Switch to Preview": "Switch to Preview",
|
||||
"When Editor Blurred": "When Editor Blurred",
|
||||
"When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click",
|
||||
"On Right Click": "On Right Click",
|
||||
"Editor Keymap": "Editor Keymap",
|
||||
"default": "default",
|
||||
"Switch to Preview": "Mudar para Pré-Visualização",
|
||||
"When Editor Blurred": "Quando o Editor Obscurece",
|
||||
"When Editor Blurred, Edit On Double Click": "Quando o Editor Obscurece, Editar com Duplo Clique",
|
||||
"On Right Click": "Ao Clicar Com o Botão Direito",
|
||||
"Editor Keymap": "Mapa de Teclado do Editor",
|
||||
"default": "padrão",
|
||||
"vim": "vim",
|
||||
"emacs": "emacs",
|
||||
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap",
|
||||
"Show line numbers in the editor": "Show line numbers in the editor",
|
||||
"Allow editor to scroll past the last line": "Allow editor to scroll past the last line",
|
||||
"Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor",
|
||||
"Preview": "Preview",
|
||||
"Preview Font Size": "Preview Font Size",
|
||||
"Preview Font Family": "Preview Font Family",
|
||||
"Code Block Theme": "Code Block Theme",
|
||||
"Allow preview to scroll past the last line": "Allow preview to scroll past the last line",
|
||||
"Show line numbers for preview code blocks": "Show line numbers for preview code blocks",
|
||||
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
|
||||
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
||||
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
||||
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter",
|
||||
"⚠️ Please restart boostnote after you change the keymap": "⚠️ Por favor, reinicia o Boostnote depois de alterar o mapa de teclado.",
|
||||
"Show line numbers in the editor": "Mostrar os números das linhas no editor",
|
||||
"Allow editor to scroll past the last line": "Permitir que o editor faça scroll além da última linha",
|
||||
"Bring in web page title when pasting URL on editor": "Trazer o título da página da Web ao colar o endereço no editor",
|
||||
"Preview": "Pré-Visualização",
|
||||
"Preview Font Size": "Tamanho da Fonte da Pré-Visualização",
|
||||
"Preview Font Family": "Família da Fonte da Pré-Visualização",
|
||||
"Code Block Theme": "Tema do Bloco de Código",
|
||||
"Allow preview to scroll past the last line": "Permitir que se faça scroll além da última linha",
|
||||
"Show line numbers for preview code blocks": "Mostrar os números das linhas na pré-visualização dos blocos de código",
|
||||
"LaTeX Inline Open Delimiter": "Delimitador para Abrir Bloco LaTeX em Linha",
|
||||
"LaTeX Inline Close Delimiter": "Delimitador para Fechar Bloco LaTeX em Linha",
|
||||
"LaTeX Block Open Delimiter": "Delimitador para Abrir Bloco LaTeX",
|
||||
"LaTeX Block Close Delimiter": "Delimitador para Fechar Bloco LaTeX",
|
||||
"PlantUML Server": "PlantUML Server",
|
||||
"Community": "Community",
|
||||
"Subscribe to Newsletter": "Subscribe to Newsletter",
|
||||
"Community": "Comunidade",
|
||||
"Subscribe to Newsletter": "Subscrever à Newsletter",
|
||||
"GitHub": "GitHub",
|
||||
"Blog": "Blog",
|
||||
"Facebook Group": "Facebook Group",
|
||||
"Facebook Group": "Grupo de Facebook",
|
||||
"Twitter": "Twitter",
|
||||
"About": "About",
|
||||
"About": "Sobre",
|
||||
"Boostnote": "Boostnote",
|
||||
"An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.",
|
||||
"An open source note-taking app made for programmers just like you.": "Uma aplicação open source de bloco de notas feita para programadores como tu.",
|
||||
"Website": "Website",
|
||||
"Development": "Development",
|
||||
" : Development configurations for Boostnote.": " : Development configurations for Boostnote.",
|
||||
"Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO",
|
||||
"License: GPL v3": "License: GPL v3",
|
||||
"Analytics": "Analytics",
|
||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.",
|
||||
"You can see how it works on ": "You can see how it works on ",
|
||||
"You can choose to enable or disable this option.": "You can choose to enable or disable this option.",
|
||||
"Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote",
|
||||
"Crowdfunding": "Crowdfunding",
|
||||
"Dear Boostnote users,": "Dear Boostnote users,",
|
||||
"Thank you for using Boostnote!": "Thank you for using Boostnote!",
|
||||
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.",
|
||||
"To support our growing userbase, and satisfy community expectations,": "To support our growing userbase, and satisfy community expectations,",
|
||||
"we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.",
|
||||
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!",
|
||||
"Thanks,": "Thanks,",
|
||||
"The Boostnote Team": "The Boostnote Team",
|
||||
"Support via OpenCollective": "Support via OpenCollective",
|
||||
"Language": "Language",
|
||||
"English": "English",
|
||||
"German": "German",
|
||||
"French": "French",
|
||||
"Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying",
|
||||
"All Notes": "All Notes",
|
||||
"Starred": "Starred",
|
||||
"Are you sure to ": "Are you sure to ",
|
||||
" delete": " delete",
|
||||
"this folder?": "this folder?",
|
||||
"Confirm": "Confirm",
|
||||
"Cancel": "Cancel",
|
||||
"Markdown Note": "Markdown Note",
|
||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.",
|
||||
"Snippet Note": "Snippet Note",
|
||||
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.",
|
||||
"Tab to switch format": "Tab to switch format",
|
||||
"Updated": "Updated",
|
||||
"Created": "Created",
|
||||
"Alphabetically": "Alphabetically",
|
||||
"Default View": "Default View",
|
||||
"Compressed View": "Compressed View",
|
||||
"Search": "Search",
|
||||
"Blog Type": "Blog Type",
|
||||
"Blog Address": "Blog Address",
|
||||
"Save": "Save",
|
||||
"Auth": "Auth",
|
||||
"Authentication Method": "Authentication Method",
|
||||
"Development": "Desenvolvimento",
|
||||
" : Development configurations for Boostnote.": " : Configurações de desenvolvimento para o Boostnote.",
|
||||
"Copyright (C) 2017 - 2018 BoostIO": "Direitos de Autor (C) 2017 - 2018 BoostIO",
|
||||
"License: GPL v3": "Licença: GPL v3",
|
||||
"Analytics": "Analíse de Data",
|
||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "O Boostnote coleta dados anônimos com o único propósito de melhorar a aplicação e não adquire informação pessoal ou conteúdo das tuas notas.",
|
||||
"You can see how it works on ": "Podes ver como funciona em ",
|
||||
"You can choose to enable or disable this option.": "Podes optar por activar ou desactivar esta opção.",
|
||||
"Enable analytics to help improve Boostnote": "Permitir recolha de data anônima para ajudar a melhorar o Boostnote",
|
||||
"Crowdfunding": "Financiamento Coletivo",
|
||||
"Dear Boostnote users,": "Caros(as),",
|
||||
"Thank you for using Boostnote!": "Obrigado por usar o Boostnote!",
|
||||
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "O Boostnote é usado em cerca de 200 países e regiões diferentes por uma incrível comunidade de developers.",
|
||||
"To support our growing userbase, and satisfy community expectations,": "Para continuar a apoiar o crescimento e satisfazer as expectativas da comunidade,",
|
||||
"we would like to invest more time and resources in this project.": "gostaríamos de investir mais tempo e recursos neste projeto.",
|
||||
"If you use Boostnote and see its potential, help us out by supporting the project on OpenCollective!": "Se gostas deste projeto e vês o seu potencial, podes ajudar-nos através de donativos no OpenCollective!",
|
||||
"Thanks,": "Obrigado,",
|
||||
"The Boostnote Team": "A Equipa do Boostnote",
|
||||
"Support via OpenCollective": "Suporte via OpenCollective",
|
||||
"Language": "Idioma",
|
||||
"English": "Inglês",
|
||||
"German": "Alemão",
|
||||
"French": "Francês",
|
||||
"Show \"Saved to Clipboard\" notification when copying": "Mostrar a notificação \"Guardado na Área de Transferência\" ao copiar",
|
||||
"All Notes": "Todas as Notas",
|
||||
"Starred": "Com Estrela",
|
||||
"Are you sure to ": "Tens a certeza que gostarias de ",
|
||||
" delete": " apagar",
|
||||
"this folder?": "esta pasta?",
|
||||
"Confirm": "Confirmar",
|
||||
"Cancel": "Cancelar",
|
||||
"Markdown Note": "Nota em Markdown",
|
||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Este formato permite a criação de documentos de texto. Estão disponíveis: listas de verificação, blocos de código e blocos Latex.",
|
||||
"Snippet Note": "Fragmento de Nota",
|
||||
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Este formato permite a criação de fragmentos de notas. Vários fragmentos podem ser agrupados em uma única nota.",
|
||||
"Tab to switch format": "Tab para mudar o formato",
|
||||
"Updated": "Actualizado",
|
||||
"Created": "Criado",
|
||||
"Alphabetically": "Alfabeticamente",
|
||||
"Default View": "Vista Padrão",
|
||||
"Compressed View": "Vista Comprimida",
|
||||
"Search": "Procurar",
|
||||
"Blog Type": "Tipo de Blog",
|
||||
"Blog Address": "Endereço do Blog",
|
||||
"Save": "Guardar",
|
||||
"Auth": "Autenticação",
|
||||
"Authentication Method": "Método de Autenticação",
|
||||
"JWT": "JWT",
|
||||
"USER": "USER",
|
||||
"Token": "Token",
|
||||
"Storage": "Storage",
|
||||
"Hotkeys": "Hotkeys",
|
||||
"Show/Hide Boostnote": "Show/Hide Boostnote",
|
||||
"Restore": "Restore",
|
||||
"Permanent Delete": "Permanent Delete",
|
||||
"Confirm note deletion": "Confirm note deletion",
|
||||
"This will permanently remove this note.": "This will permanently remove this note.",
|
||||
"Successfully applied!": "Successfully applied!",
|
||||
"Albanian": "Albanian",
|
||||
"Chinese (zh-CN)": "Chinese (zh-CN)",
|
||||
"Chinese (zh-TW)": "Chinese (zh-TW)",
|
||||
"Danish": "Danish",
|
||||
"Japanese": "Japanese",
|
||||
"Korean": "Korean",
|
||||
"Norwegian": "Norwegian",
|
||||
"Polish": "Polish",
|
||||
"Portuguese": "Portuguese",
|
||||
"Spanish": "Spanish",
|
||||
"Unsaved Changes!": "Unsaved Changes!",
|
||||
"Russian": "Russian",
|
||||
"Editor Rulers": "Editor Rulers",
|
||||
"Enable": "Enable",
|
||||
"Disable": "Disable",
|
||||
"Sanitization": "Sanitization",
|
||||
"Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)",
|
||||
"Allow styles": "Allow styles",
|
||||
"Allow dangerous html tags": "Allow dangerous html tags",
|
||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.",
|
||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠"
|
||||
"Storage": "Armazenamento",
|
||||
"Hotkeys": "Teclas de Atalho",
|
||||
"Show/Hide Boostnote": "Mostrar/Esconder Boostnote",
|
||||
"Restore": "Restaurar",
|
||||
"Permanent Delete": "Apagar Permanentemente",
|
||||
"Confirm note deletion": "Confirmar o apagamento da nota",
|
||||
"This will permanently remove this note.": "Isto irá remover permanentemente esta nota.",
|
||||
"Successfully applied!": "Aplicado com Sucesso!",
|
||||
"Albanian": "Albanês",
|
||||
"Chinese (zh-CN)": "Chinês (zh-CN)",
|
||||
"Chinese (zh-TW)": "Chinês (zh-TW)",
|
||||
"Danish": "Dinamarquês",
|
||||
"Japanese": "Japonês",
|
||||
"Korean": "Coreano",
|
||||
"Norwegian": "Norueguês",
|
||||
"Polish": "Polaco",
|
||||
"Portuguese": "Português (pt-PT)",
|
||||
"Spanish": "Espanhol",
|
||||
"Unsaved Changes!": "Alterações Não Guardadas!",
|
||||
"Russian": "Russo",
|
||||
"Editor Rulers": "Réguas do Editor",
|
||||
"Enable": "Activar",
|
||||
"Disable": "Desactivar",
|
||||
"Sanitization": "Sanitização",
|
||||
"Only allow secure html tags (recommended)": "Perminar somente tags html seguras (recomendado)",
|
||||
"Allow styles": "Permitir Estilos",
|
||||
"Allow dangerous html tags": "Permitir tags html perigosas",
|
||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "Converter setas de texto em simbolos. ⚠ Isto irá interferir no use de comentários em HTML em Markdown.",
|
||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ Você colou um link referente a um anexo que não pôde ser encontrado no local de armazenamento desta nota. A vinculação de anexos de referência de links só é suportada se o local de origem e de destino for o mesmo de armazenamento. Por favor, arraste e solte o anexo na nota! ⚠"
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@
|
||||
"UserName": "Имя пользователя",
|
||||
"Password": "Пароль",
|
||||
"Russian": "Русский",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Editor Rulers": "Editor Rulers",
|
||||
"Enable": "Enable",
|
||||
"Disable": "Disable",
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
"Spanish": "Spanish",
|
||||
"Unsaved Changes!": "Unsaved Changes!",
|
||||
"Russian": "Russian",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Editor Rulers": "Editor Rulers",
|
||||
"Enable": "Enable",
|
||||
"Disable": "Disable",
|
||||
|
||||
182
locales/th.json
Normal file
182
locales/th.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"Notes": "โน๊ต",
|
||||
"Tags": "แท็ก",
|
||||
"Preferences": "ตั้งค่า",
|
||||
"Make a note": "สร้างโน๊ต",
|
||||
"Ctrl": "Ctrl",
|
||||
"Ctrl(^)": "Ctrl(^)",
|
||||
"to create a new note": "เพื่อสร้างโน๊ต",
|
||||
"Toggle Mode": "Toggle Mode",
|
||||
"Add tag...": "เพิ่มแท็ก...",
|
||||
"Trash": "ถังขยะ",
|
||||
"MODIFICATION DATE": "แก้ไขเมื่อ",
|
||||
"Words": "คำ",
|
||||
"Letters": "ตัวอักษร",
|
||||
"STORAGE": "แหล่งจัดเก็บ",
|
||||
"FOLDER": "โฟลเดอร์",
|
||||
"CREATION DATE": "สร้างเมื่อ",
|
||||
"NOTE LINK": "NOTE LINK",
|
||||
".md": ".md",
|
||||
".txt": ".txt",
|
||||
".html": ".html",
|
||||
"Print": "พิมพ์",
|
||||
"Your preferences for Boostnote": "การตั้งค่าของคุณสำหรับ Boostnote",
|
||||
"Help": "ช่วยเหลือ",
|
||||
"Hide Help": "ซ่อนการช่วยเหลือ",
|
||||
"Storages": "แหล่งจัดเก็บ",
|
||||
"Add Storage Location": "เพิ่มแหล่งจัดเก็บ",
|
||||
"Add Folder": "เพิ่มโฟลเดอร์",
|
||||
"Select Folder": "เลือกโฟลเดอร์",
|
||||
"Open Storage folder": "เปิดโฟลเดอร์แหล่งจัดเก็บ",
|
||||
"Unlink": "ยกเลิกการลิงค์",
|
||||
"Edit": "แก้ไข",
|
||||
"Delete": "ลบ",
|
||||
"Interface": "หน้าตาโปรแกรม",
|
||||
"Interface Theme": "ธีมของโปรแกรม",
|
||||
"Default": "ค่าเริ่มต้น",
|
||||
"White": "โทนสว่าง",
|
||||
"Solarized Dark": "Solarized Dark",
|
||||
"Dark": "โทนมืด",
|
||||
"Show a confirmation dialog when deleting notes": "แสดงหน้าต่างยืนยันเมื่อทำการลบโน๊ต",
|
||||
"Disable Direct Write (It will be applied after restarting)": "ปิด Direct Write (It will be applied after restarting)",
|
||||
"Show only related tags": "แสดงเฉพาะแท็กที่เกี่ยวข้อง",
|
||||
"Editor Theme": "ธีมของ Editor",
|
||||
"Editor Font Size": "ขนาดอักษรของ Editor",
|
||||
"Editor Font Family": "แบบอักษรของ Editor",
|
||||
"Editor Indent Style": "รูปแบบการย่อหน้าของ Editor",
|
||||
"Spaces": "ช่องว่าง",
|
||||
"Tabs": "แท็บ",
|
||||
"Switch to Preview": "Switch to Preview",
|
||||
"When Editor Blurred": "When Editor Blurred",
|
||||
"When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click",
|
||||
"On Right Click": "On Right Click",
|
||||
"Editor Keymap": "รูปแบบคีย์ลัดของ Editor",
|
||||
"default": "ค่าเริ่มต้น",
|
||||
"vim": "vim",
|
||||
"emacs": "emacs",
|
||||
"⚠️ Please restart boostnote after you change the keymap": "⚠️ กรุณาปิดและเปิดโปรแกรมใหม่ หลังจากคุณเปลี่ยนคีย์ลัด",
|
||||
"Show line numbers in the editor": "แสดงหมายเลขบรรทัด",
|
||||
"Allow editor to scroll past the last line": "อนุญาตให้เลื่อน Scroll เลยบรรทัดสุดท้ายได้",
|
||||
"Enable smart quotes": "เปิด Smart quotes",
|
||||
"Bring in web page title when pasting URL on editor": "แสดงชื่อ Title ของเว็บไซต์เมื่อวางลิงค์ใน Editor",
|
||||
"Preview": "พรีวิว",
|
||||
"Preview Font Size": "ขนาดอักษร",
|
||||
"Preview Font Family": "แบบอักษร",
|
||||
"Code block Theme": "ธีมของ Code block",
|
||||
"Allow preview to scroll past the last line": "อนุญาตให้เลื่อน Scroll เลยบรรทัดสุดท้ายได้",
|
||||
"Show line numbers for preview code blocks": "แสดงหมายเลขบรรทัดใน Code block",
|
||||
"LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter",
|
||||
"LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter",
|
||||
"LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter",
|
||||
"LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter",
|
||||
"PlantUML Server": "เซิฟเวอร์ของ PlantUML",
|
||||
"Community": "ชุมชนผู้ใช้",
|
||||
"Subscribe to Newsletter": "สมัครรับข่าวสาร",
|
||||
"GitHub": "GitHub",
|
||||
"Blog": "บล็อก",
|
||||
"Facebook Group": "กลุ่ม Facebook",
|
||||
"Twitter": "Twitter",
|
||||
"About": "เกี่ยวกับ",
|
||||
"Boostnote": "Boostnote",
|
||||
"An open source note-taking app made for programmers just like you.": "เป็นแอพพลิเคชันจดบันทึก ที่ออกแบบมาเพื่อโปรแกรมเมอร์อย่างคุณ.",
|
||||
"Website": "เว็บไซต์",
|
||||
"Development": "การพัฒนา",
|
||||
" : Development configurations for Boostnote.": " : การตั้งค่าต่างๆสำหรับการพัฒนา Boostnote.",
|
||||
"Copyright (C) 2017 - 2018 BoostIO": "สงวนลิขสิทธิ์ (C) 2017 - 2018 BoostIO",
|
||||
"License: GPL v3": "License: GPL v3",
|
||||
"Analytics": "การวิเคราะห์",
|
||||
"Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote จะเก็บข้อมูลแบบไม่ระบุตัวตนเพื่อนำไปใช้ในการปรับปรุงแอพพลิเคชันเท่านั้น, และจะไม่มีการเก็บข้อมูลส่วนตัวใดๆของคุณ เช่น ข้อมูลในโน๊ตของคุณอย่างเด็ดขาด.",
|
||||
"You can see how it works on ": "คุณสามารถดูรายละเอียดเพิ่มเติมได้ที่ ",
|
||||
"You can choose to enable or disable this option.": "คุณสามารถเลือกที่จะเปิดหรือปิดตัวเลือกนี้ได้.",
|
||||
"Enable analytics to help improve Boostnote": "เปิดการวิเคราะห์ สำหรับการนำไปปรับปรุงพัฒนา Boostnote",
|
||||
"Crowdfunding": "การระดมทุนสาธารณะ",
|
||||
"Dear everyone,": "สวัสดีทุกคน,",
|
||||
"Thank you for using Boostnote!": "ขอขอบคุณที่เลือกใช้ Boostnote!",
|
||||
"Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "มีการใช้งาน Boostnote จากสังคมผู้ใช้ที่เป็น Developer มากกว่า 200 ประเทศทั่วโลกจากหลากหลายภูมิภาค.",
|
||||
"To continue supporting this growth, and to satisfy community expectations,": "เพื่อให้เกิดการสนับสนุนให้เกิดการเติบโตอย่างต่อเนื่อง, และเพื่อพัฒนาให้ตรงตามความต้องการของชุมชนผู้ใช้,",
|
||||
"we would like to invest more time and resources in this project.": "เราต้องใช้เวลา และการลงทุนด้านทรัพยากรสำหรับโครงการนี้.",
|
||||
"If you like this project and see its potential, you can help by supporting us on OpenCollective!": "ถ้าคุณชอบและมองเห็นความเป็นไปได้ในอนาคต, คุณสามารถช่วยเหลือด้วยการสนับสนุนเราผ่าน OpenCollective!",
|
||||
"Thanks,": "ขอขอบคุณ,",
|
||||
"Boostnote maintainers": "กลุ่มผู้พัฒนา Boostnote",
|
||||
"Support via OpenCollective": "สนับสนุนผ่าน OpenCollective",
|
||||
"Language": "ภาษา",
|
||||
"English": "English",
|
||||
"German": "German",
|
||||
"French": "French",
|
||||
"Show \"Saved to Clipboard\" notification when copying": "แสดงการแจ้งเตือน \"บันทึกไปยังคลิปบอร์ด\" เมื่อทำการคัดลอก",
|
||||
"All Notes": "โน๊ตทั้งหมด",
|
||||
"Starred": "รายการโปรด",
|
||||
"Are you sure to ": "คุณแน่ใจหรือไม่ที่จะ ",
|
||||
" delete": " ลบ",
|
||||
"this folder?": "โฟลเดอร์นี้?",
|
||||
"Confirm": "ยืนยัน",
|
||||
"Cancel": "ยกเลิก",
|
||||
"Markdown Note": "โน๊ต Markdown",
|
||||
"This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "รูปแบบนี้ใช้สำหรับสร้างเอกสารทั่วไป. รองรับการเขียนเช็คลิสต์, แทรกโค้ด และการเขียนโดยใช้ Latex.",
|
||||
"Snippet Note": "โน๊ต Snippet",
|
||||
"This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "รูปแบบนี้ใช้สำหรับสร้าง Code snippets. สามารถรวมหลาย Snippets เป็นโน๊ตเดียวกันได้.",
|
||||
"Tab to switch format": "กด Tab เพื่อเปลี่ยนรูปแบบที่เลือก",
|
||||
"Updated": "เรียงตามอัพเดท",
|
||||
"Created": "เรียงตามเวลาที่สร้างโน๊ต",
|
||||
"Alphabetically": "เรียงตามอักษร",
|
||||
"Counter": "Counter",
|
||||
"Default View": "มุมมองปกติ",
|
||||
"Compressed View": "มุมมองหนาแน่น",
|
||||
"Search": "ค้นหา",
|
||||
"Blog Type": "ประเภทของบล็อก",
|
||||
"Blog Address": "ที่อยู่ของบล็อก",
|
||||
"Save": "บันทึก",
|
||||
"Auth": "การยืนยันตัวตน",
|
||||
"Authentication Method": "รูปแบบการยืนยันตัวตน",
|
||||
"JWT": "JWT",
|
||||
"USER": "USER",
|
||||
"Token": "Token",
|
||||
"Storage": "แหล่งจัดเก็บ",
|
||||
"Hotkeys": "คีย์ลัด",
|
||||
"Show/Hide Boostnote": "แสดง/ซ่อน Boostnote",
|
||||
"Toggle editor mode": "เปิด/ปิด Editor mode",
|
||||
"Restore": "กู้คืน",
|
||||
"Permanent Delete": "ลบถาวร",
|
||||
"Confirm note deletion": "ยืนยันการลบโน๊ต",
|
||||
"This will permanently remove this note.": "โน๊ตของคุณจะถูกลบอย่างถาวร.",
|
||||
"Successfully applied!": "สำเร็จ!",
|
||||
"Albanian": "Albanian",
|
||||
"Chinese (zh-CN)": "Chinese (zh-CN)",
|
||||
"Chinese (zh-TW)": "Chinese (zh-TW)",
|
||||
"Danish": "Danish",
|
||||
"Japanese": "Japanese",
|
||||
"Korean": "Korean",
|
||||
"Norwegian": "Norwegian",
|
||||
"Polish": "Polish",
|
||||
"Portuguese": "Portuguese",
|
||||
"Spanish": "Spanish",
|
||||
"You have to save!": "คุณจำเป็นต้องบันทึก!",
|
||||
"UserName": "UserName",
|
||||
"Password": "Password",
|
||||
"Russian": "Russian",
|
||||
"Hungarian": "Hungarian",
|
||||
"Thai": "Thai (ภาษาไทย)",
|
||||
"Command(⌘)": "Command(⌘)",
|
||||
"Add Storage": "เพิ่มแหล่งจัดเก็บ",
|
||||
"Name": "ชื่อ",
|
||||
"Type": "ชนิด",
|
||||
"File System": "ระบบไฟล์",
|
||||
"Setting up 3rd-party cloud storage integration:": "ดูวิธีการตั้งค่า หากต้องการใช้งานแบบลิงค์ไฟล์ร่วมกับผู้ให้บริการเก็บข้อมูลบนคลาวด์",
|
||||
"Cloud-Syncing-and-Backup": "Cloud-Syncing-and-Backup",
|
||||
"Location": "ที่อยู่",
|
||||
"Add": "เพิ่ม",
|
||||
"Unlink Storage": "ยกเลิกการลิงค์ Storage",
|
||||
"Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.": "การยกเลิกการลิงค์ จะเป็นการลบการลิงค์แหล่งจัดเก็บออกไปจาก Boostnote. แต่ไฟล์ข้อมูลจะไม่ถูกลบ, หากต้องการลบข้อมูล กรุณาลบโพลเดอร์ของข้อมูลในเครื่องของท่านด้วยตัวเอง.",
|
||||
"Editor Rulers": "ไม้บรรทัด Editor",
|
||||
"Enable": "เปิด",
|
||||
"Disable": "ปิด",
|
||||
"Sanitization": "Sanitization",
|
||||
"Only allow secure html tags (recommended)": "อนุญาตเฉพาะ HTML tag ที่มีความปลอดภัย (แนะนำ)",
|
||||
"Render newlines in Markdown paragraphs as <br>": "ใช้ <br> แทนอักขระขึ้นบรรทัดใหม่ในข้อความ Markdown",
|
||||
"Allow styles": "อนุญาตการใช้ styles",
|
||||
"Allow dangerous html tags": "อนุญาตให้ใช้ html tags ที่ไม่ปลอดภัย",
|
||||
"Convert textual arrows to beautiful signs. ⚠ This will interfere with using HTML comments in your Markdown.": "แปลงลูกศรจากรูปแบบข้อความให้เป็นสัญลักษณ์. ⚠ สิ่งนี้จะเป็นการแทรกโดยใช้ HTML comment ลงไปใน Markdown ที่คุณเขียน.",
|
||||
"⚠ You have pasted a link referring an attachment that could not be found in the storage location of this note. Pasting links referring attachments is only supported if the source and destination location is the same storage. Please Drag&Drop the attachment instead! ⚠": "⚠ ไม่พบไฟล์แนบในโน๊ตนี้ จากลิงค์ที่คุณได้วาง. คุณสามารถวางลิงค์ที่อ้างอิงไปยังไฟล์แนบ เฉพาะกรณีที่ต้นทาง และปลายทางที่อ้างถึงนั้นอยู่ใน 'แหล่งจัดเก็บ เดียวกัน. กรุณาใช้การลากและวางเพื่อใส่ไฟล์แนบแทน! ⚠",
|
||||
"Enable smart table editor": "เปิดการใช้ Smart table editor",
|
||||
"Snippet Default Language": "ทำการ Snippet ภาษาที่เป็นค่าเริ่มต้น"
|
||||
}
|
||||
15
package.json
15
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "boost",
|
||||
"productName": "Boostnote",
|
||||
"version": "0.11.9",
|
||||
"version": "0.11.10",
|
||||
"main": "index.js",
|
||||
"description": "Boostnote",
|
||||
"license": "GPL-3.0",
|
||||
@@ -15,7 +15,7 @@
|
||||
"dev": "node dev-scripts/dev.js"
|
||||
},
|
||||
"config": {
|
||||
"electron-version": "2.0.7"
|
||||
"electron-version": "3.0.3"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -56,7 +56,7 @@
|
||||
"codemirror": "^5.40.2",
|
||||
"codemirror-mode-elixir": "^1.1.1",
|
||||
"electron-config": "^1.0.0",
|
||||
"electron-gh-releases": "^2.0.2",
|
||||
"electron-gh-releases": "^2.0.4",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"file-uri-to-path": "^1.0.0",
|
||||
"file-url": "^2.0.2",
|
||||
@@ -73,6 +73,7 @@
|
||||
"lodash": "^4.11.1",
|
||||
"lodash-move": "^1.1.1",
|
||||
"markdown-it": "^6.0.1",
|
||||
"markdown-it-abbr": "^1.0.4",
|
||||
"markdown-it-admonition": "^1.0.4",
|
||||
"markdown-it-emoji": "^1.1.1",
|
||||
"markdown-it-footnote": "^3.0.0",
|
||||
@@ -82,6 +83,8 @@
|
||||
"markdown-it-named-headers": "^0.0.4",
|
||||
"markdown-it-plantuml": "^1.1.0",
|
||||
"markdown-it-smartarrows": "^1.0.1",
|
||||
"markdown-it-sub": "^1.0.0",
|
||||
"markdown-it-sup": "^1.0.0",
|
||||
"markdown-toc": "^1.2.0",
|
||||
"mdurl": "^1.0.1",
|
||||
"mermaid": "^8.0.0-rc.8",
|
||||
@@ -104,7 +107,9 @@
|
||||
"sanitize-html": "^1.18.2",
|
||||
"striptags": "^2.2.1",
|
||||
"unique-slug": "2.0.0",
|
||||
"uuid": "^3.2.1"
|
||||
"uuid": "^3.2.1",
|
||||
"turndown":"^4.0.2",
|
||||
"turndown-plugin-gfm":"^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^0.25.0",
|
||||
@@ -126,7 +131,7 @@
|
||||
"css-loader": "^0.19.0",
|
||||
"devtron": "^1.1.0",
|
||||
"dom-storage": "^2.0.2",
|
||||
"electron": "2.0.7",
|
||||
"electron": "3.0.3",
|
||||
"electron-packager": "^12.0.0",
|
||||
"eslint": "^3.13.1",
|
||||
"eslint-config-standard": "^6.2.1",
|
||||
|
||||
@@ -30,7 +30,7 @@ Issues on Boostnote can be funded by anyone and the money will be distributed to
|
||||
- [Facebook Group](https://www.facebook.com/groups/boostnote/)
|
||||
- [Twitter](https://twitter.com/boostnoteapp)
|
||||
- [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/enQtMzkxOTk4ODkyNzc0LThkNmMzY2VlZjVhYTNiYjE5YjQyZGVjNTJlYTY1OGMyZTFjNGU5YTUyYjUzOWZhYTU4OTVlNDYyNDFjYWMzNDM)
|
||||
- [Blog](https://boostlog.io/tags/boostnote)
|
||||
- [Blog](https://medium.com/boostnote)
|
||||
- [Reddit](https://www.reddit.com/r/Boostnote/)
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
exports[`TagListItem renders correctly 1`] = `
|
||||
<div
|
||||
className="tagList-itemContainer"
|
||||
onContextMenu={[Function]}
|
||||
>
|
||||
<div
|
||||
className="tagList-itemNarrow"
|
||||
|
||||
61
tests/fixtures/markdowns.js
vendored
61
tests/fixtures/markdowns.js
vendored
@@ -50,11 +50,70 @@ const smartQuotes = 'This is a "QUOTE".'
|
||||
|
||||
const breaks = 'This is the first line.\nThis is the second line.'
|
||||
|
||||
const abbrevations = `
|
||||
## abbr
|
||||
|
||||
The HTML specification
|
||||
is maintained by the W3C.
|
||||
|
||||
*[HTML]: Hyper Text Markup Language
|
||||
*[W3C]: World Wide Web Consortium
|
||||
`
|
||||
|
||||
const subTexts = `
|
||||
## sub
|
||||
|
||||
H~2~0
|
||||
`
|
||||
|
||||
const supTexts = `
|
||||
## sup
|
||||
|
||||
29^th^
|
||||
`
|
||||
|
||||
const deflists = `
|
||||
## definition list
|
||||
|
||||
### list 1
|
||||
|
||||
Term 1
|
||||
~ Definition 1
|
||||
|
||||
Term 2
|
||||
~ Definition 2a
|
||||
~ Definition 2b
|
||||
|
||||
Term 3
|
||||
~
|
||||
|
||||
|
||||
### list 2
|
||||
|
||||
Term 1
|
||||
|
||||
: Definition 1
|
||||
|
||||
Term 2 with *inline markup*
|
||||
|
||||
: Definition 2
|
||||
|
||||
{ some code, part of Definition 2 }
|
||||
|
||||
Third paragraph of definition 2.
|
||||
`
|
||||
const shortcuts = '<kbd>Ctrl</kbd>\n\n[[Ctrl]]'
|
||||
|
||||
export default {
|
||||
basic,
|
||||
codeblock,
|
||||
katex,
|
||||
checkboxes,
|
||||
smartQuotes,
|
||||
breaks
|
||||
breaks,
|
||||
abbrevations,
|
||||
subTexts,
|
||||
supTexts,
|
||||
deflists,
|
||||
shortcuts
|
||||
}
|
||||
|
||||
@@ -20,7 +20,47 @@ test('findNoteTitle#find should return a correct title (string)', t => {
|
||||
|
||||
testCases.forEach(testCase => {
|
||||
const [input, expected] = testCase
|
||||
t.is(findNoteTitle(input), expected, `Test for find() input: ${input} expected: ${expected}`)
|
||||
t.is(findNoteTitle(input, false), expected, `Test for find() input: ${input} expected: ${expected}`)
|
||||
})
|
||||
})
|
||||
|
||||
test('findNoteTitle#find should ignore front matter when enableFrontMatterTitle=false', t => {
|
||||
// [input, expected]
|
||||
const testCases = [
|
||||
['---\nlayout: test\ntitle: hoge hoge hoge \n---\n# fuga', '# fuga'],
|
||||
['---\ntitle:hoge\n---\n# fuga', '# fuga'],
|
||||
['title: fuga\n# hoge', '# hoge']
|
||||
]
|
||||
|
||||
testCases.forEach(testCase => {
|
||||
const [input, expected] = testCase
|
||||
t.is(findNoteTitle(input, false), expected, `Test for find() input: ${input} expected: ${expected}`)
|
||||
})
|
||||
})
|
||||
|
||||
test('findNoteTitle#find should respect front matter when enableFrontMatterTitle=true', t => {
|
||||
// [input, expected]
|
||||
const testCases = [
|
||||
['---\nlayout: test\ntitle: hoge hoge hoge \n---\n# fuga', 'hoge hoge hoge'],
|
||||
['---\ntitle:hoge\n---\n# fuga', 'hoge'],
|
||||
['title: fuga\n# hoge', '# hoge']
|
||||
]
|
||||
|
||||
testCases.forEach(testCase => {
|
||||
const [input, expected] = testCase
|
||||
t.is(findNoteTitle(input, true), expected, `Test for find() input: ${input} expected: ${expected}`)
|
||||
})
|
||||
})
|
||||
|
||||
test('findNoteTitle#find should respect frontMatterTitleField when provided', t => {
|
||||
// [input, expected]
|
||||
const testCases = [
|
||||
['---\ntitle: hoge\n---\n# fuga', '# fuga'],
|
||||
['---\ncustom: hoge\n---\n# fuga', 'hoge']
|
||||
]
|
||||
|
||||
testCases.forEach(testCase => {
|
||||
const [input, expected] = testCase
|
||||
t.is(findNoteTitle(input, true, 'custom'), expected, `Test for find() input: ${input} expected: ${expected}`)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -43,3 +43,28 @@ test('Markdown.render() should render line breaks correctly', t => {
|
||||
const renderedNonBreaks = newmd.render(markdownFixtures.breaks)
|
||||
t.snapshot(renderedNonBreaks)
|
||||
})
|
||||
|
||||
test('Markdown.render() should renders abbrevations correctly', t => {
|
||||
const rendered = md.render(markdownFixtures.abbrevations)
|
||||
t.snapshot(rendered)
|
||||
})
|
||||
|
||||
test('Markdown.render() should renders sub correctly', t => {
|
||||
const rendered = md.render(markdownFixtures.subTexts)
|
||||
t.snapshot(rendered)
|
||||
})
|
||||
|
||||
test('Markdown.render() should renders sup correctly', t => {
|
||||
const rendered = md.render(markdownFixtures.supTexts)
|
||||
t.snapshot(rendered)
|
||||
})
|
||||
|
||||
test('Markdown.render() should renders definition lists correctly', t => {
|
||||
const rendered = md.render(markdownFixtures.deflists)
|
||||
t.snapshot(rendered)
|
||||
})
|
||||
|
||||
test('Markdown.render() should render shortcuts correctly', t => {
|
||||
const rendered = md.render(markdownFixtures.shortcuts)
|
||||
t.snapshot(rendered)
|
||||
})
|
||||
|
||||
@@ -18,6 +18,14 @@ Generated by [AVA](https://ava.li).
|
||||
This is the second line.</p>␊
|
||||
`
|
||||
|
||||
## Markdown.render() should render shortcuts correctly
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
`<p data-line="0"><kbd>Ctrl</kbd></p>␊
|
||||
<p data-line="2"><kbd>Ctrl</kbd></p>␊
|
||||
`
|
||||
|
||||
## Markdown.render() should renders KaTeX correctly
|
||||
|
||||
> Snapshot 1
|
||||
@@ -25,13 +33,22 @@ Generated by [AVA](https://ava.li).
|
||||
`<span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>c</mi><mo>=</mo><mi>p</mi><mi>m</mi><mi>s</mi><mi>q</mi><mi>r</mi><mi>t</mi><mrow><msup><mi>a</mi><mn>2</mn></msup><mo>+</mo><msup><mi>b</mi><mn>2</mn></msup></mrow></mrow><annotation encoding="application/x-tex">c = pmsqrt{a^2 + b^2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="strut" style="height:0.8641079999999999em;"></span><span class="strut bottom" style="height:1.0585479999999998em;vertical-align:-0.19444em;"></span><span class="base"><span class="mord mathit">c</span><span class="mord rule" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mord rule" style="margin-right:0.2777777777777778em;"></span><span class="mord mathit">p</span><span class="mord mathit">m</span><span class="mord mathit">s</span><span class="mord mathit" style="margin-right:0.03588em;">q</span><span class="mord mathit" style="margin-right:0.02778em;">r</span><span class="mord mathit">t</span><span class="mord"><span class="mord"><span class="mord mathit">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641079999999999em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord rule" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mord rule" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathit">b</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641079999999999em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span></span></span>␊
|
||||
`
|
||||
|
||||
## Markdown.render() should renders abbrevations correctly
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
`<h2 data-line="1" id="abbr">abbr</h2>␊
|
||||
<p data-line="3">The <abbr title="Hyper Text Markup Language">HTML</abbr> specification<br />␊
|
||||
is maintained by the <abbr title="World Wide Web Consortium">W3C</abbr>.</p>␊
|
||||
`
|
||||
|
||||
## Markdown.render() should renders checkboxes
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
`<ul>␊
|
||||
<li class="taskListItem"><input type="checkbox" id="checkbox-2" /> Unchecked</li>␊
|
||||
<li class="taskListItem checked"><input type="checkbox" checked id="checkbox-3" /> Checked</li>␊
|
||||
<li class="taskListItem" data-line="1"><input type="checkbox" id="checkbox-2" /> Unchecked</li>␊
|
||||
<li class="taskListItem checked" data-line="2"><input type="checkbox" checked id="checkbox-3" /> Checked</li>␊
|
||||
</ul>␊
|
||||
`
|
||||
|
||||
@@ -46,6 +63,37 @@ Generated by [AVA](https://ava.li).
|
||||
</code>␊
|
||||
</pre>`
|
||||
|
||||
## Markdown.render() should renders definition lists correctly
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
`<h2 data-line="1" id="definition-list">definition list</h2>␊
|
||||
<h3 data-line="3" id="list-1">list 1</h3>␊
|
||||
<dl>␊
|
||||
<dt data-line="5">Term 1</dt>␊
|
||||
<dd data-line="6">Definition 1</dd>␊
|
||||
<dt data-line="8">Term 2</dt>␊
|
||||
<dd data-line="9">Definition 2a</dd>␊
|
||||
<dd data-line="10">Definition 2b</dd>␊
|
||||
</dl>␊
|
||||
<p data-line="12">Term 3<br />␊
|
||||
~</p>␊
|
||||
<h3 data-line="16" id="list-2">list 2</h3>␊
|
||||
<dl>␊
|
||||
<dt data-line="18">Term 1</dt>␊
|
||||
<dd data-line="20">␊
|
||||
<p data-line="20">Definition 1</p>␊
|
||||
</dd>␊
|
||||
<dt data-line="22">Term 2 with <em>inline markup</em></dt>␊
|
||||
<dd data-line="24">␊
|
||||
<p data-line="24">Definition 2</p>␊
|
||||
<pre><code> { some code, part of Definition 2 }␊
|
||||
</code></pre>␊
|
||||
<p data-line="28">Third paragraph of definition 2.</p>␊
|
||||
</dd>␊
|
||||
</dl>␊
|
||||
`
|
||||
|
||||
## Markdown.render() should renders markdown correctly
|
||||
|
||||
> Snapshot 1
|
||||
@@ -55,31 +103,47 @@ Generated by [AVA](https://ava.li).
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/L0qNPLsvmyM" frameborder="0" allowfullscreen></iframe>␊
|
||||
<h2 data-line="6" id="Docs-%F0%9F%93%9D">Docs 📝</h2>␊
|
||||
<ul>␊
|
||||
<li><a href="https://hackernoon.com/boostnote-boost-your-happiness-productivity-and-creativity-315034efeebe">Boostnote | Boost your happiness, productivity and creativity.</a></li>␊
|
||||
<li><a href="https://github.com/BoostIO/Boostnote/wiki/Cloud-Syncing-and-Backup">Cloud Syncing & Backups</a></li>␊
|
||||
<li><a href="https://github.com/BoostIO/Boostnote/wiki/Sync-Data-Across-Desktop-and-Mobile-apps">How to sync your data across Desktop and Mobile apps</a></li>␊
|
||||
<li><a href="https://github.com/BoostIO/Boostnote/wiki/Evernote">Convert data from <strong>Evernote</strong> to Boostnote.</a></li>␊
|
||||
<li><a href="https://github.com/BoostIO/Boostnote/wiki/Keyboard-Shortcuts">Keyboard Shortcuts</a></li>␊
|
||||
<li><a href="https://github.com/BoostIO/Boostnote/wiki/Keymaps-in-Editor-mode">Keymaps in Editor mode</a></li>␊
|
||||
<li><a href="https://github.com/BoostIO/Boostnote/wiki/Syntax-Highlighting">How to set syntax highlight in Snippet note</a></li>␊
|
||||
<li data-line="7"><a href="https://hackernoon.com/boostnote-boost-your-happiness-productivity-and-creativity-315034efeebe">Boostnote | Boost your happiness, productivity and creativity.</a></li>␊
|
||||
<li data-line="8"><a href="https://github.com/BoostIO/Boostnote/wiki/Cloud-Syncing-and-Backup">Cloud Syncing & Backups</a></li>␊
|
||||
<li data-line="9"><a href="https://github.com/BoostIO/Boostnote/wiki/Sync-Data-Across-Desktop-and-Mobile-apps">How to sync your data across Desktop and Mobile apps</a></li>␊
|
||||
<li data-line="10"><a href="https://github.com/BoostIO/Boostnote/wiki/Evernote">Convert data from <strong>Evernote</strong> to Boostnote.</a></li>␊
|
||||
<li data-line="11"><a href="https://github.com/BoostIO/Boostnote/wiki/Keyboard-Shortcuts">Keyboard Shortcuts</a></li>␊
|
||||
<li data-line="12"><a href="https://github.com/BoostIO/Boostnote/wiki/Keymaps-in-Editor-mode">Keymaps in Editor mode</a></li>␊
|
||||
<li data-line="13"><a href="https://github.com/BoostIO/Boostnote/wiki/Syntax-Highlighting">How to set syntax highlight in Snippet note</a></li>␊
|
||||
</ul>␊
|
||||
<hr />␊
|
||||
<h2 data-line="17" id="Article-Archive-%F0%9F%93%9A">Article Archive 📚</h2>␊
|
||||
<ul>␊
|
||||
<li><a href="http://bit.ly/2mOJPu7">Reddit English</a></li>␊
|
||||
<li><a href="https://www.reddit.com/r/boostnote_es/">Reddit Spanish</a></li>␊
|
||||
<li><a href="https://www.reddit.com/r/boostnote_cn/">Reddit Chinese</a></li>␊
|
||||
<li><a href="https://www.reddit.com/r/boostnote_jp/">Reddit Japanese</a></li>␊
|
||||
<li data-line="18"><a href="http://bit.ly/2mOJPu7">Reddit English</a></li>␊
|
||||
<li data-line="19"><a href="https://www.reddit.com/r/boostnote_es/">Reddit Spanish</a></li>␊
|
||||
<li data-line="20"><a href="https://www.reddit.com/r/boostnote_cn/">Reddit Chinese</a></li>␊
|
||||
<li data-line="21"><a href="https://www.reddit.com/r/boostnote_jp/">Reddit Japanese</a></li>␊
|
||||
</ul>␊
|
||||
<hr />␊
|
||||
<h2 data-line="25" id="Community-%F0%9F%8D%BB">Community 🍻</h2>␊
|
||||
<ul>␊
|
||||
<li><a href="http://bit.ly/2AWWzkD">GitHub</a></li>␊
|
||||
<li><a href="http://bit.ly/2z8BUJZ">Twitter</a></li>␊
|
||||
<li><a href="http://bit.ly/2jcca8t">Facebook Group</a></li>␊
|
||||
<li data-line="26"><a href="http://bit.ly/2AWWzkD">GitHub</a></li>␊
|
||||
<li data-line="27"><a href="http://bit.ly/2z8BUJZ">Twitter</a></li>␊
|
||||
<li data-line="28"><a href="http://bit.ly/2jcca8t">Facebook Group</a></li>␊
|
||||
</ul>␊
|
||||
`
|
||||
|
||||
## Markdown.render() should renders sub correctly
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
`<h2 data-line="1" id="sub">sub</h2>␊
|
||||
<p data-line="3">H<sub>2</sub>0</p>␊
|
||||
`
|
||||
|
||||
## Markdown.render() should renders sup correctly
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
`<h2 data-line="1" id="sup">sup</h2>␊
|
||||
<p data-line="3">29<sup>th</sup></p>␊
|
||||
`
|
||||
|
||||
## Markdown.render() should text with quotes correctly
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
Binary file not shown.
178
yarn.lock
178
yarn.lock
@@ -93,6 +93,10 @@ abab@^1.0.3, abab@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e"
|
||||
|
||||
abab@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f"
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||
@@ -138,6 +142,10 @@ acorn@^5.0.0, acorn@^5.3.0, acorn@^5.5.0:
|
||||
version "5.5.3"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9"
|
||||
|
||||
acorn@^5.5.3:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8"
|
||||
|
||||
ajv-keywords@^1.0.0:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
|
||||
@@ -2242,6 +2250,12 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
|
||||
dependencies:
|
||||
cssom "0.3.x"
|
||||
|
||||
cssstyle@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.0.0.tgz#79b16d51ec5591faec60e688891f15d2a5705129"
|
||||
dependencies:
|
||||
cssom "0.3.x"
|
||||
|
||||
ctype@0.5.3:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f"
|
||||
@@ -2761,7 +2775,7 @@ domelementtype@~1.1.1:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
|
||||
|
||||
domexception@^1.0.0:
|
||||
domexception@^1.0.0, domexception@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90"
|
||||
dependencies:
|
||||
@@ -2816,20 +2830,6 @@ electron-config@^1.0.0:
|
||||
dependencies:
|
||||
conf "^1.0.0"
|
||||
|
||||
electron-download@^3.0.1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-3.3.0.tgz#2cfd54d6966c019c4d49ad65fbe65cc9cdef68c8"
|
||||
dependencies:
|
||||
debug "^2.2.0"
|
||||
fs-extra "^0.30.0"
|
||||
home-path "^1.0.1"
|
||||
minimist "^1.2.0"
|
||||
nugget "^2.0.0"
|
||||
path-exists "^2.1.0"
|
||||
rc "^1.1.2"
|
||||
semver "^5.3.0"
|
||||
sumchecker "^1.2.0"
|
||||
|
||||
electron-download@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.0.tgz#bf932c746f2f87ffcc09d1dd472f2ff6b9187845"
|
||||
@@ -2844,7 +2844,21 @@ electron-download@^4.0.0:
|
||||
semver "^5.3.0"
|
||||
sumchecker "^2.0.1"
|
||||
|
||||
electron-gh-releases@^2.0.2:
|
||||
electron-download@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8"
|
||||
dependencies:
|
||||
debug "^3.0.0"
|
||||
env-paths "^1.0.0"
|
||||
fs-extra "^4.0.1"
|
||||
minimist "^1.2.0"
|
||||
nugget "^2.0.1"
|
||||
path-exists "^3.0.0"
|
||||
rc "^1.2.1"
|
||||
semver "^5.4.1"
|
||||
sumchecker "^2.0.2"
|
||||
|
||||
electron-gh-releases@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/electron-gh-releases/-/electron-gh-releases-2.0.4.tgz#198c07a0970fb8e80fcc67bd0b4198a010923dc3"
|
||||
dependencies:
|
||||
@@ -2928,12 +2942,12 @@ electron-winstaller@^2.2.0:
|
||||
lodash.template "^4.2.2"
|
||||
temp "^0.8.3"
|
||||
|
||||
electron@2.0.7:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-2.0.7.tgz#f7ce410433298e319032ce31f0e6ffd709ff052c"
|
||||
electron@3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-3.0.3.tgz#2857ed8d37c1b46e0a75a72684800252255f3243"
|
||||
dependencies:
|
||||
"@types/node" "^8.0.24"
|
||||
electron-download "^3.0.1"
|
||||
electron-download "^4.1.0"
|
||||
extract-zip "^1.0.3"
|
||||
|
||||
emojis-list@^2.0.0:
|
||||
@@ -3048,10 +3062,6 @@ es6-promise@^3.1.2:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
|
||||
|
||||
es6-promise@^4.0.5:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29"
|
||||
|
||||
es6-set@~0.1.5:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
|
||||
@@ -3097,6 +3107,17 @@ escodegen@^1.6.1, escodegen@^1.9.0:
|
||||
optionalDependencies:
|
||||
source-map "~0.6.1"
|
||||
|
||||
escodegen@^1.9.1:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589"
|
||||
dependencies:
|
||||
esprima "^3.1.3"
|
||||
estraverse "^4.2.0"
|
||||
esutils "^2.0.2"
|
||||
optionator "^0.8.1"
|
||||
optionalDependencies:
|
||||
source-map "~0.6.1"
|
||||
|
||||
escope@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
|
||||
@@ -3761,16 +3782,6 @@ fs-extra@0.26.7, fs-extra@^0.26.0, fs-extra@^0.26.7:
|
||||
path-is-absolute "^1.0.0"
|
||||
rimraf "^2.2.8"
|
||||
|
||||
fs-extra@^0.30.0:
|
||||
version "0.30.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0"
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
jsonfile "^2.1.0"
|
||||
klaw "^1.0.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
rimraf "^2.2.8"
|
||||
|
||||
fs-extra@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950"
|
||||
@@ -3786,7 +3797,7 @@ fs-extra@^2.0.0:
|
||||
graceful-fs "^4.1.2"
|
||||
jsonfile "^2.1.0"
|
||||
|
||||
fs-extra@^4.0.0:
|
||||
fs-extra@^4.0.0, fs-extra@^4.0.1:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
|
||||
dependencies:
|
||||
@@ -4329,10 +4340,6 @@ home-or-tmp@^2.0.0:
|
||||
os-homedir "^1.0.0"
|
||||
os-tmpdir "^1.0.1"
|
||||
|
||||
home-path@^1.0.1:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/home-path/-/home-path-1.0.6.tgz#d549dc2465388a7f8667242c5b31588d29af29fc"
|
||||
|
||||
hooker@~0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/hooker/-/hooker-0.2.3.tgz#b834f723cc4a242aa65963459df6d984c5d3d959"
|
||||
@@ -5414,6 +5421,37 @@ jsdom@^11.5.1:
|
||||
ws "^4.0.0"
|
||||
xml-name-validator "^3.0.0"
|
||||
|
||||
jsdom@^11.9.0:
|
||||
version "11.12.0"
|
||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
|
||||
dependencies:
|
||||
abab "^2.0.0"
|
||||
acorn "^5.5.3"
|
||||
acorn-globals "^4.1.0"
|
||||
array-equal "^1.0.0"
|
||||
cssom ">= 0.3.2 < 0.4.0"
|
||||
cssstyle "^1.0.0"
|
||||
data-urls "^1.0.0"
|
||||
domexception "^1.0.1"
|
||||
escodegen "^1.9.1"
|
||||
html-encoding-sniffer "^1.0.2"
|
||||
left-pad "^1.3.0"
|
||||
nwsapi "^2.0.7"
|
||||
parse5 "4.0.0"
|
||||
pn "^1.1.0"
|
||||
request "^2.87.0"
|
||||
request-promise-native "^1.0.5"
|
||||
sax "^1.2.4"
|
||||
symbol-tree "^3.2.2"
|
||||
tough-cookie "^2.3.4"
|
||||
w3c-hr-time "^1.0.1"
|
||||
webidl-conversions "^4.0.2"
|
||||
whatwg-encoding "^1.0.3"
|
||||
whatwg-mimetype "^2.1.0"
|
||||
whatwg-url "^6.4.1"
|
||||
ws "^5.2.0"
|
||||
xml-name-validator "^3.0.0"
|
||||
|
||||
jsdom@^9.4.2:
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4"
|
||||
@@ -5579,7 +5617,7 @@ lcid@^1.0.0:
|
||||
dependencies:
|
||||
invert-kv "^1.0.0"
|
||||
|
||||
left-pad@^1.2.0:
|
||||
left-pad@^1.2.0, left-pad@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e"
|
||||
|
||||
@@ -5824,6 +5862,10 @@ map-visit@^1.0.0:
|
||||
dependencies:
|
||||
object-visit "^1.0.0"
|
||||
|
||||
markdown-it-abbr@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-abbr/-/markdown-it-abbr-1.0.4.tgz#d66b5364521cbb3dd8aa59dadfba2fb6865c8fd8"
|
||||
|
||||
markdown-it-admonition@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-admonition/-/markdown-it-admonition-1.0.4.tgz#d7bbc7eb1fe6168fc8cc304de7a9d8c993acb2f5"
|
||||
@@ -5864,6 +5906,14 @@ markdown-it-smartarrows@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-smartarrows/-/markdown-it-smartarrows-1.0.1.tgz#b570e9c0ff9812e0db6ace19afa5ba12b64bb9a7"
|
||||
|
||||
markdown-it-sub@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-sub/-/markdown-it-sub-1.0.0.tgz#375fd6026eae7ddcb012497f6411195ea1e3afe8"
|
||||
|
||||
markdown-it-sup@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-sup/-/markdown-it-sup-1.0.0.tgz#cb9c9ff91a5255ac08f3fd3d63286e15df0a1fc3"
|
||||
|
||||
markdown-it@^5.0.3:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-5.1.0.tgz#25286b8465bac496f3f1b77eed544643e9bd718d"
|
||||
@@ -6438,7 +6488,7 @@ npmlog@^4.0.2:
|
||||
gauge "~2.7.3"
|
||||
set-blocking "~2.0.0"
|
||||
|
||||
nugget@^2.0.0:
|
||||
nugget@^2.0.0, nugget@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/nugget/-/nugget-2.0.1.tgz#201095a487e1ad36081b3432fa3cada4f8d071b0"
|
||||
dependencies:
|
||||
@@ -6466,6 +6516,10 @@ nwsapi@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.0.tgz#7c8faf4ad501e1d17a651ebc5547f966b547c5c7"
|
||||
|
||||
nwsapi@^2.0.7:
|
||||
version "2.0.8"
|
||||
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.8.tgz#e3603579b7e162b3dbedae4fb24e46f771d8fa24"
|
||||
|
||||
oauth-sign@~0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.6.0.tgz#7dbeae44f6ca454e1f168451d630746735813ce3"
|
||||
@@ -6736,7 +6790,7 @@ path-browserify@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a"
|
||||
|
||||
path-exists@^2.0.0, path-exists@^2.1.0:
|
||||
path-exists@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
|
||||
dependencies:
|
||||
@@ -7224,6 +7278,10 @@ pseudomap@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
|
||||
|
||||
psl@^1.1.24:
|
||||
version "1.1.29"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67"
|
||||
|
||||
punycode@1.3.2:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
||||
@@ -7310,7 +7368,7 @@ raw-body@2.3.2:
|
||||
iconv-lite "0.4.19"
|
||||
unpipe "1.0.0"
|
||||
|
||||
rc@^1.0.1, rc@^1.1.2, rc@^1.1.6, rc@^1.1.7:
|
||||
rc@^1.0.1, rc@^1.1.2, rc@^1.1.6, rc@^1.1.7, rc@^1.2.1:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
||||
dependencies:
|
||||
@@ -7752,7 +7810,7 @@ request@2.55.0:
|
||||
tough-cookie ">=0.12.0"
|
||||
tunnel-agent "~0.4.0"
|
||||
|
||||
request@^2.45.0, request@^2.79.0, request@^2.83.0:
|
||||
request@^2.45.0, request@^2.79.0, request@^2.83.0, request@^2.87.0:
|
||||
version "2.87.0"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e"
|
||||
dependencies:
|
||||
@@ -8558,14 +8616,7 @@ stylus@^0.52.4:
|
||||
sax "0.5.x"
|
||||
source-map "0.1.x"
|
||||
|
||||
sumchecker@^1.2.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-1.3.1.tgz#79bb3b4456dd04f18ebdbc0d703a1d1daec5105d"
|
||||
dependencies:
|
||||
debug "^2.2.0"
|
||||
es6-promise "^4.0.5"
|
||||
|
||||
sumchecker@^2.0.1:
|
||||
sumchecker@^2.0.1, sumchecker@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-2.0.2.tgz#0f42c10e5d05da5d42eea3e56c3399a37d6c5b3e"
|
||||
dependencies:
|
||||
@@ -8791,6 +8842,13 @@ tough-cookie@>=0.12.0, tough-cookie@>=2.3.3, tough-cookie@^2.3.2, tough-cookie@^
|
||||
dependencies:
|
||||
punycode "^1.4.1"
|
||||
|
||||
tough-cookie@^2.3.4:
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
|
||||
dependencies:
|
||||
psl "^1.1.24"
|
||||
punycode "^1.4.1"
|
||||
|
||||
tr46@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
|
||||
@@ -8847,6 +8905,16 @@ tunnel-agent@~0.4.0:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
|
||||
|
||||
turndown-plugin-gfm@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz#6f8678a361f35220b2bdf5619e6049add75bf1c7"
|
||||
|
||||
turndown@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/turndown/-/turndown-4.0.2.tgz#c3ddb8ba32a3665723599be2f4e7860adb6042ae"
|
||||
dependencies:
|
||||
jsdom "^11.9.0"
|
||||
|
||||
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||
version "0.14.5"
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||
@@ -9384,6 +9452,12 @@ ws@^4.0.0:
|
||||
async-limiter "~1.0.0"
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
ws@^5.2.0:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
|
||||
xdg-basedir@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
|
||||
|
||||
Reference in New Issue
Block a user