diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index d676a1a4..257bb0a9 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -72,6 +72,8 @@ export default class CodeEditor extends React.Component { } } this.editorActivityHandler = () => this.handleEditorActivity() + + this.turndownService = new TurndownService() } handleSearch (msg) { diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js index d43a7693..ed836cb5 100644 --- a/browser/components/MarkdownEditor.js +++ b/browser/components/MarkdownEditor.js @@ -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 @@ -76,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 }, () => { @@ -88,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) }) } } diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index 6643d796..d9ff7074 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -16,6 +16,8 @@ import convertModeName from 'browser/lib/convertModeName' import copy from 'copy-to-clipboard' import mdurl from 'mdurl' import exportNote from 'browser/main/lib/dataApi/exportNote' +import { escapeHtmlCharacters } from 'browser/lib/utils' +import yaml from 'js-yaml' import context from 'browser/lib/context' import i18n from 'browser/lib/i18n' import fs from 'fs' @@ -737,7 +739,6 @@ export default class MarkdownPreview extends React.Component { el.addEventListener('click', this.linkClickHandler) }) } catch (e) { - console.error(e) el.className = 'flowchart-error' el.innerHTML = 'Flowchart parse error: ' + e.message } @@ -758,7 +759,6 @@ export default class MarkdownPreview extends React.Component { el.addEventListener('click', this.linkClickHandler) }) } catch (e) { - console.error(e) el.className = 'sequence-error' el.innerHTML = 'Sequence diagram parse error: ' + e.message } @@ -769,14 +769,21 @@ export default class MarkdownPreview extends React.Component { this.refs.root.contentWindow.document.querySelectorAll('.chart'), el => { try { - const chartConfig = JSON.parse(el.innerHTML) + const format = el.attributes.getNamedItem('data-format').value + const chartConfig = format === 'yaml' ? yaml.load(el.innerHTML) : JSON.parse(el.innerHTML) el.innerHTML = '' - var canvas = document.createElement('canvas') + + const canvas = document.createElement('canvas') el.appendChild(canvas) - /* eslint-disable no-new */ - new Chart(canvas, chartConfig) + + const height = el.attributes.getNamedItem('data-height') + if (height && height.value !== 'undefined') { + el.style.height = height.value + 'vh' + canvas.height = height.value + 'vh' + } + + const chart = new Chart(canvas, chartConfig) } catch (e) { - console.error(e) el.className = 'chart-error' el.innerHTML = 'chartjs diagram parse error: ' + e.message } diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl index e091331b..b7f219b8 100644 --- a/browser/components/markdown.styl +++ b/browser/components/markdown.styl @@ -209,41 +209,39 @@ code text-decoration none margin-right 2px pre - padding 0.5em !important + padding 0.5rem !important border solid 1px #D1D1D1 border-radius 5px overflow-x auto - margin 0 0 1em + margin 0 0 1rem display flex line-height 1.4em - &.flowchart, &.sequence, &.chart - display flex - justify-content center - background-color white - &.CodeMirror - height initial - flex-wrap wrap - &>code - flex 1 - overflow-x auto code background-color inherit margin 0 padding 0 border none border-radius 0 + &.CodeMirror + height initial + flex-wrap wrap + &>code + flex 1 + overflow-x auto + &.mermaid svg + max-width 100% !important &>span.filename - width 100% - border-radius: 5px 0px 0px 0px - margin -8px 100% 8px -8px - padding 0px 6px + margin -0.5rem 100% 0.5rem -0.5rem + padding 0.125rem 0.375rem background-color #777; color white + &:empty + display none &>span.lineNumber display none font-size 1em - padding 0.5em 0 - margin -0.5em 0.5em -0.5em -0.5em + padding 0.5rem 0 + margin -0.5rem 0.5rem -0.5rem -0.5rem border-right 1px solid text-align right border-top-left-radius 4px @@ -375,6 +373,49 @@ 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 + + .chart, .flowchart, .mermaid, .sequence + display flex + justify-content center + background-color white + max-width 100% + flex-grow 1 + + canvas, svg + max-width 100% !important + themeDarkBackground = darken(#21252B, 10%) themeDarkText = #f9f9f9 themeDarkBorder = lighten(themeDarkBackground, 20%) @@ -425,6 +466,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 themeSolarizedDarkTableOdd = $ui-solarized-dark-noteDetail-backgroundColor themeSolarizedDarkTableEven = darken($ui-solarized-dark-noteDetail-backgroundColor, 10%) @@ -452,6 +501,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 themeMonokaiTableOdd = $ui-monokai-noteDetail-backgroundColor themeMonokaiTableEven = darken($ui-monokai-noteDetail-backgroundColor, 10%) @@ -481,6 +538,14 @@ body[data-theme="monokai"] border-right solid 1px themeMonokaiTableBorder 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 themeDraculaTableOdd = $ui-dracula-noteDetail-backgroundColor themeDraculaTableEven = darken($ui-dracula-noteDetail-backgroundColor, 10%) @@ -509,4 +574,12 @@ body[data-theme="dracula"] &:last-child border-right solid 1px themeDraculaTableBorder kbd - background-color themeDarkBackground \ No newline at end of file + background-color themeDarkBackground + dl + border-color themeDarkBorder + background-color themeDraculaTableHead + dt + border-color themeDarkBorder + dd + border-color themeDarkBorder + background-color $ui-dracula-noteDetail-backgroundColor diff --git a/browser/components/render/MermaidRender.js b/browser/components/render/MermaidRender.js index e8784d9d..7a3b3ea2 100644 --- a/browser/components/render/MermaidRender.js +++ b/browser/components/render/MermaidRender.js @@ -11,9 +11,9 @@ function getRandomInt (min, max) { } function getId () { - var pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' - var id = 'm-' - for (var i = 0; i < 7; i++) { + const pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' + let id = 'm-' + for (let i = 0; i < 7; i++) { id += pool[getRandomInt(0, 16)] } return id @@ -21,16 +21,20 @@ function getId () { function render (element, content, theme) { try { + const height = element.attributes.getNamedItem('data-height') + if (height && height.value !== 'undefined') { + element.style.height = height.value + 'vh' + } let isDarkTheme = theme === 'dark' || theme === 'solarized-dark' || theme === 'monokai' || theme === 'dracula' mermaidAPI.initialize({ theme: isDarkTheme ? 'dark' : 'default', - themeCSS: isDarkTheme ? darkThemeStyling : '' + themeCSS: isDarkTheme ? darkThemeStyling : '', + useMaxWidth: false }) mermaidAPI.render(getId(), content, (svgGraph) => { element.innerHTML = svgGraph }) } catch (e) { - console.error(e) element.className = 'mermaid-error' element.innerHTML = 'mermaid diagram parse error: ' + e.message } diff --git a/browser/lib/Languages.js b/browser/lib/Languages.js index 1a798fdf..8c3747a9 100644 --- a/browser/lib/Languages.js +++ b/browser/lib/Languages.js @@ -48,9 +48,13 @@ const languages = [ locale: 'pl' }, { - name: 'Portuguese', + name: 'Portuguese (PT-BR)', locale: 'pt-BR' }, + { + name: 'Portuguese (PT-PT)', + locale: 'pt-PT' + }, { name: 'Russian', locale: 'ru' diff --git a/browser/lib/markdown-it-deflist.js b/browser/lib/markdown-it-deflist.js new file mode 100644 index 00000000..db14c636 --- /dev/null +++ b/browser/lib/markdown-it-deflist.js @@ -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' ] }) +} diff --git a/browser/lib/markdown-it-fence.js b/browser/lib/markdown-it-fence.js new file mode 100644 index 00000000..fd1c759d --- /dev/null +++ b/browser/lib/markdown-it-fence.js @@ -0,0 +1,132 @@ +'use strict' + +module.exports = function (md, renderers, defaultRenderer) { + const paramsRE = /^[ \t]*([\w+#-]+)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/ + + function fence (state, startLine, endLine) { + let pos = state.bMarks[startLine] + state.tShift[startLine] + let max = state.eMarks[startLine] + + if (state.sCount[startLine] - state.blkIndent >= 4 || pos + 3 > max) { + return false + } + + const marker = state.src.charCodeAt(pos) + if (!(marker === 96 || marker === 126)) { + return false + } + + let mem = pos + pos = state.skipChars(pos, marker) + + let len = pos - mem + if (len < 3) { + return false + } + + const markup = state.src.slice(mem, pos) + const params = state.src.slice(pos, max) + + let nextLine = startLine + let haveEndMarker = false + + while (true) { + nextLine++ + if (nextLine >= endLine) { + break + } + + pos = mem = state.bMarks[nextLine] + state.tShift[nextLine] + max = state.eMarks[nextLine] + + if (pos < max && state.sCount[nextLine] < state.blkIndent) { + break + } + if (state.src.charCodeAt(pos) !== marker || state.sCount[nextLine] - state.blkIndent >= 4) { + continue + } + + pos = state.skipChars(pos, marker) + + if (pos - mem < len) { + continue + } + + pos = state.skipSpaces(pos) + + if (pos >= max) { + haveEndMarker = true + break + } + } + + len = state.sCount[startLine] + state.line = nextLine + (haveEndMarker ? 1 : 0) + + const parameters = {} + let langType = '' + let fileName = '' + let firstLineNumber = 1 + + let match = paramsRE.exec(params) + if (match) { + if (match[1]) { + langType = match[1] + } + if (match[3]) { + fileName = match[3] + } + if (match[4]) { + firstLineNumber = parseInt(match[4], 10) + } + + if (match[2]) { + const params = match[2] + const regex = /(\w[-\w]*)(?:=(?:'(.*?[^\\])?'|"(.*?[^\\])?"|([^'"][^\s]*)))?/g + + let name, value + while ((match = regex.exec(params))) { + name = match[1] + value = match[2] || match[3] || match[4] || null + + const height = /^(\d+)h$/.exec(name) + if (height && !value) { + parameters.height = height[1] + } else { + parameters[name] = value + } + } + } + } + + let token + if (renderers[langType]) { + token = state.push(`${langType}_fence`, 'div', 0) + } else { + token = state.push('_fence', 'code', 0) + } + + token.langType = langType + token.fileName = fileName + token.firstLineNumber = firstLineNumber + token.parameters = parameters + + token.content = state.getLines(startLine + 1, nextLine, len, true) + token.markup = markup + token.map = [startLine, state.line] + + return true + } + + md.block.ruler.before('fence', '_fence', fence, { + alt: ['paragraph', 'reference', 'blockquote', 'list'] + }) + + for (const name in renderers) { + md.renderer.rules[`${name}_fence`] = (tokens, index) => renderers[name](tokens[index]) + } + + if (defaultRenderer) { + md.renderer.rules['_fence'] = (tokens, index) => defaultRenderer(tokens[index]) + } +} diff --git a/browser/lib/markdown-it-sanitize-html.js b/browser/lib/markdown-it-sanitize-html.js index bd3d452e..8f6d86a8 100644 --- a/browser/lib/markdown-it-sanitize-html.js +++ b/browser/lib/markdown-it-sanitize-html.js @@ -15,7 +15,7 @@ module.exports = function sanitizePlugin (md, options) { options ) } - if (state.tokens[tokenIdx].type === 'fence') { + if (state.tokens[tokenIdx].type === '_fence') { // escapeHtmlCharacters has better performance state.tokens[tokenIdx].content = escapeHtmlCharacters( state.tokens[tokenIdx].content, diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index 7fbb5a38..13ef758a 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -28,32 +28,6 @@ class Markdown { html: true, xhtmlOut: true, breaks: config.preview.breaks, - highlight: function (str, lang) { - const delimiter = ':' - const langInfo = lang.split(delimiter) - const langType = langInfo[0] - const fileName = langInfo[1] || '' - const firstLineNumber = parseInt(langInfo[2], 10) - - if (langType === 'flowchart') { - return `
${str}`
- }
- if (langType === 'sequence') {
- return `${str}`
- }
- if (langType === 'chart') {
- return `${str}`
- }
- if (langType === 'mermaid') {
- return `${str}`
- }
- return '' +
- '' + fileName + '' +
- createGutter(str, firstLineNumber) +
- '' +
- str +
- ''
- },
sanitize: 'STRICT'
}
@@ -153,10 +127,50 @@ 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'), {
+ chart: token => {
+ if (token.parameters.hasOwnProperty('yaml')) {
+ token.parameters.format = 'yaml'
+ }
+
+ return `+ ${token.fileName} +` + }, + flowchart: token => { + return `${token.content}+
+ ${token.fileName} +` + }, + mermaid: token => { + return `${token.content}+
+ ${token.fileName} +` + }, + sequence: token => { + return `${token.content}+
+ ${token.fileName} +` + } + }, token => { + return `${token.content}+
+ ${token.fileName}
+ ${createGutter(token.content, token.firstLineNumber)}
+ ${token.content}
+ `
+ })
+
const deflate = require('markdown-it-plantuml/lib/deflate')
this.md.use(require('markdown-it-plantuml'), '', {
generateSource: function (umlCode) {
@@ -257,9 +271,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]])
}
diff --git a/browser/main/Detail/ToggleModeButton.js b/browser/main/Detail/ToggleModeButton.js
index c414a3e5..7c026429 100644
--- a/browser/main/Detail/ToggleModeButton.js
+++ b/browser/main/Detail/ToggleModeButton.js
@@ -1,26 +1,26 @@
-import PropTypes from 'prop-types'
-import React from 'react'
-import CSSModules from 'browser/lib/CSSModules'
-import styles from './ToggleModeButton.styl'
-import i18n from 'browser/lib/i18n'
-
-const ToggleModeButton = ({
- onClick, editorType
-}) => (
- The HTML specification
␊
+ is maintained by the W3C.
filename.js2var project = 'boostnote';␊
+ `␊
+ filename.js␊
+ 2␊
+ var project = 'boostnote';␊
+ ␊
+
`
+
+## Markdown.render() should renders definition lists correctly
+
+> Snapshot 1
+
+ `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.
␊
+ ␊
+
␊
`
## Markdown.render() should renders markdown correctly
@@ -60,31 +103,47 @@ Generated by [AVA](https://ava.li).
␊
Docs 📝
␊
␊
- - Boostnote | Boost your happiness, productivity and creativity.
␊
- - Cloud Syncing & Backups
␊
- - How to sync your data across Desktop and Mobile apps
␊
- - Convert data from Evernote to Boostnote.
␊
- - Keyboard Shortcuts
␊
- - Keymaps in Editor mode
␊
- - How to set syntax highlight in Snippet note
␊
+ - Boostnote | Boost your happiness, productivity and creativity.
␊
+ - Cloud Syncing & Backups
␊
+ - How to sync your data across Desktop and Mobile apps
␊
+ - Convert data from Evernote to Boostnote.
␊
+ - Keyboard Shortcuts
␊
+ - Keymaps in Editor mode
␊
+ - How to set syntax highlight in Snippet note
␊
␊
␊
Article Archive 📚
␊
␊
- - Reddit English
␊
- - Reddit Spanish
␊
- - Reddit Chinese
␊
- - Reddit Japanese
␊
+ - Reddit English
␊
+ - Reddit Spanish
␊
+ - Reddit Chinese
␊
+ - Reddit Japanese
␊
␊
␊
Community 🍻
␊
␊
- - GitHub
␊
- - Twitter
␊
- - Facebook Group
␊
+ - GitHub
␊
+ - Twitter
␊
+ - Facebook Group
␊
␊
`
+## Markdown.render() should renders sub correctly
+
+> Snapshot 1
+
+ `sub
␊
+ H20
␊
+ `
+
+## Markdown.render() should renders sup correctly
+
+> Snapshot 1
+
+ `sup
␊
+ 29th
␊
+ `
+
## Markdown.render() should text with quotes correctly
> Snapshot 1
diff --git a/tests/lib/snapshots/markdown-test.js.snap b/tests/lib/snapshots/markdown-test.js.snap
index 5b8d1095..b60aae57 100644
Binary files a/tests/lib/snapshots/markdown-test.js.snap and b/tests/lib/snapshots/markdown-test.js.snap differ
diff --git a/yarn.lock b/yarn.lock
index 6326fd57..a17b9f74 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2826,20 +2826,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"
@@ -2854,7 +2840,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:
@@ -2938,12 +2938,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:
@@ -3058,10 +3058,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"
@@ -3782,16 +3778,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"
@@ -3807,7 +3793,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:
@@ -4350,10 +4336,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"
@@ -5344,7 +5326,7 @@ js-yaml@^3.10.0, js-yaml@^3.5.1, js-yaml@^3.7.0:
argparse "^1.0.7"
esprima "^4.0.0"
-js-yaml@^3.8.1:
+js-yaml@^3.12.0, js-yaml@^3.8.1:
version "3.12.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
dependencies:
@@ -5866,6 +5848,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"
@@ -5906,6 +5892,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"
@@ -6480,7 +6474,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:
@@ -6782,7 +6776,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:
@@ -7353,7 +7347,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:
@@ -7367,8 +7361,8 @@ rcedit@^1.0.0:
resolved "https://registry.yarnpkg.com/rcedit/-/rcedit-1.1.0.tgz#ae21c28d4efdd78e95fcab7309a5dd084920b16a"
react-autosuggest@^9.4.0:
- version "9.4.0"
- resolved "https://registry.yarnpkg.com/react-autosuggest/-/react-autosuggest-9.4.0.tgz#3146bc9afa4f171bed067c542421edec5ca94294"
+ version "9.4.2"
+ resolved "https://registry.yarnpkg.com/react-autosuggest/-/react-autosuggest-9.4.2.tgz#18cc0bebeebda3d24328e3da301f061a444ae223"
dependencies:
prop-types "^15.5.10"
react-autowhatever "^10.1.2"
@@ -8584,14 +8578,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: