From a59100176184b9700da1cb1b838106a6baf6736c Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Sat, 25 Aug 2018 20:18:59 +0200 Subject: [PATCH 01/31] add parameter to specify the height of the diagram, fixing #2335 --- browser/components/render/MermaidRender.js | 1 + browser/lib/markdown.js | 2 +- browser/styles/index.styl | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/browser/components/render/MermaidRender.js b/browser/components/render/MermaidRender.js index 12dce327..bac52b2c 100644 --- a/browser/components/render/MermaidRender.js +++ b/browser/components/render/MermaidRender.js @@ -28,6 +28,7 @@ function render (element, content, theme) { }) mermaidAPI.render(getId(), content, (svgGraph) => { element.innerHTML = svgGraph + element.style.height = element.attributes.getNamedItem('data-height').value + 'vh' }) } catch (e) { console.error(e) diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index 49fd2f86..d4bc72e4 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -44,7 +44,7 @@ class Markdown { return `
${str}
` } if (langType === 'mermaid') { - return `
${str}
` + return `
${str}
` } return '
' +
           '' + fileName + '' +
diff --git a/browser/styles/index.styl b/browser/styles/index.styl
index 7d32e77a..8f917fcf 100644
--- a/browser/styles/index.styl
+++ b/browser/styles/index.styl
@@ -383,4 +383,8 @@ modalmonokai()
   width 100%
   background-color $ui-monokai-backgroundColor
   overflow hidden
-  border-radius $modal-border-radius
\ No newline at end of file
+  border-radius $modal-border-radius
+
+pre.mermaid svg {
+  max-width 100% !important
+}
\ No newline at end of file

From 094e4c5da82b869a383c8a5e98847ea84edf9698 Mon Sep 17 00:00:00 2001
From: Baptiste Augrain 
Date: Mon, 27 Aug 2018 02:41:56 +0200
Subject: [PATCH 02/31] add support to abbreviations, subscript text,
 superscript text and definition lists

---
 browser/components/markdown.styl   |  55 ++++++-
 browser/lib/markdown-it-deflist.js | 221 +++++++++++++++++++++++++++++
 browser/lib/markdown.js            |   4 +
 package.json                       |   3 +
 yarn.lock                          |  12 ++
 5 files changed, 294 insertions(+), 1 deletion(-)
 create mode 100644 browser/lib/markdown-it-deflist.js

diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl
index 03503231..4f326e08 100644
--- a/browser/components/markdown.styl
+++ b/browser/components/markdown.styl
@@ -371,6 +371,35 @@ for name, val in admonition_types
         color: val[color]
         content: val[icon]
 
+dl
+  margin 2em 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 18%
+  padding 1%
+
+dd
+  border-top 1px solid borderColor
+  flex-basis 78%
+  max-width 78%
+  padding 1%
+  min-height 1.55em
+  background-color $ui-noteDetail-backgroundColor
+
+dd + dd
+  margin-left 20%
+
 themeDarkBackground = darken(#21252B, 10%)
 themeDarkText = #f9f9f9
 themeDarkBorder = lighten(themeDarkBackground, 20%)
@@ -421,6 +450,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%)
@@ -448,6 +485,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%)
@@ -476,4 +521,12 @@ body[data-theme="monokai"]
         &:last-child
           border-right solid 1px themeMonokaiTableBorder
   kbd
-    background-color themeDarkBackground
\ No newline at end of file
+    background-color themeDarkBackground
+  dl
+    border-color themeDarkBorder
+    background-color themeMonokaiTableHead
+  dt
+    border-color themeDarkBorder
+  dd
+    border-color themeDarkBorder
+    background-color $ui-monokai-noteDetail-backgroundColor
\ No newline at end of file
diff --git a/browser/lib/markdown-it-deflist.js b/browser/lib/markdown-it-deflist.js
new file mode 100644
index 00000000..5dd02267
--- /dev/null
+++ b/browser/lib/markdown-it-deflist.js
@@ -0,0 +1,221 @@
+'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,
+      nextLine,
+      offset,
+      oldDDIndent,
+      oldIndent,
+      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 = [ nextLine, 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'
+
+        state.md.block.tokenize(state, ddLine, endLine, true)
+
+        // 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.js b/browser/lib/markdown.js
index 49fd2f86..a3e230af 100644
--- a/browser/lib/markdown.js
+++ b/browser/lib/markdown.js
@@ -149,6 +149,10 @@ class Markdown {
     })
     this.md.use(require('markdown-it-kbd'))
     this.md.use(require('markdown-it-admonition'))
+    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'))
 
     const deflate = require('markdown-it-plantuml/lib/deflate')
     this.md.use(require('markdown-it-plantuml'), '', {
diff --git a/package.json b/package.json
index e9949adf..ee814f3b 100644
--- a/package.json
+++ b/package.json
@@ -71,6 +71,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",
@@ -80,6 +81,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",
     "mdurl": "^1.0.1",
     "mermaid": "^8.0.0-rc.8",
     "moment": "^2.10.3",
diff --git a/yarn.lock b/yarn.lock
index 4ecfa51b..d32f1520 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5723,6 +5723,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"
@@ -5763,6 +5767,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"

From 646151e02081850df4b916a619540b9e3e6c735f Mon Sep 17 00:00:00 2001
From: Baptiste Augrain 
Date: Mon, 27 Aug 2018 19:12:28 +0200
Subject: [PATCH 03/31] allows compact definition lists

---
 browser/lib/markdown-it-deflist.js | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/browser/lib/markdown-it-deflist.js b/browser/lib/markdown-it-deflist.js
index 5dd02267..d0cdb656 100644
--- a/browser/lib/markdown-it-deflist.js
+++ b/browser/lib/markdown-it-deflist.js
@@ -46,10 +46,12 @@ module.exports = function definitionListPlugin (md) {
       listLines,
       listTokIdx,
       max,
+      newEndLine,
       nextLine,
       offset,
       oldDDIndent,
       oldIndent,
+      oldLineMax,
       oldParentType,
       oldSCount,
       oldTShift,
@@ -150,7 +152,16 @@ module.exports = function definitionListPlugin (md) {
         state.tight = true
         state.parentType = 'deflist'
 
-        state.md.block.tokenize(state, ddLine, endLine, true)
+        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) {

From f57c4f390d5546393f4473485f4f03281140be35 Mon Sep 17 00:00:00 2001
From: Baptiste Augrain 
Date: Mon, 27 Aug 2018 23:16:21 +0200
Subject: [PATCH 04/31] fix lint errors

---
 browser/lib/markdown-it-deflist.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/browser/lib/markdown-it-deflist.js b/browser/lib/markdown-it-deflist.js
index d0cdb656..f3c58009 100644
--- a/browser/lib/markdown-it-deflist.js
+++ b/browser/lib/markdown-it-deflist.js
@@ -155,12 +155,12 @@ module.exports = function definitionListPlugin (md) {
         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

From 49db1c8244c4ff80185b3f6b4a0a5531d78fb6b7 Mon Sep 17 00:00:00 2001
From: Baptiste Augrain 
Date: Sat, 8 Sep 2018 19:28:06 +0200
Subject: [PATCH 05/31] fix style to match table padding

---
 browser/components/markdown.styl | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl
index d6b541d7..15f89f89 100644
--- a/browser/components/markdown.styl
+++ b/browser/components/markdown.styl
@@ -361,7 +361,7 @@ for name, val in admonition_types
     .admonition.{name}
         @extend $admonition
         border-left-color: val[color]
-    
+
     .admonition.{name}>.admonition-title
         @extend $admonition-title
         border-bottom-color: .1rem solid rgba(val[color], 0.2)
@@ -387,16 +387,17 @@ dt
   font-weight bold
   text-align right
   overflow hidden
-  flex-basis 18%
-  padding 1%
+  flex-basis 20%
+  padding 6px 13px
+  box-sizing border-box
 
 dd
   border-top 1px solid borderColor
-  flex-basis 78%
-  max-width 78%
-  padding 1%
-  min-height 1.55em
+  flex-basis 80%
+  padding 6px 13px
+  min-height 2.5em
   background-color $ui-noteDetail-backgroundColor
+  box-sizing border-box
 
 dd + dd
   margin-left 20%

From 189b245b1db18d1ecfdb4034187eb09ae0b0a46a Mon Sep 17 00:00:00 2001
From: Baptiste Augrain 
Date: Thu, 13 Sep 2018 11:07:19 +0200
Subject: [PATCH 06/31] add attributes to fence blocks

---
 browser/components/MarkdownPreview.js      |  13 ++-
 browser/components/markdown.styl           |  32 +++--
 browser/components/render/MermaidRender.js |  18 +--
 browser/lib/markdown-it-fence.js           | 130 +++++++++++++++++++++
 browser/lib/markdown.js                    |  59 +++++-----
 5 files changed, 207 insertions(+), 45 deletions(-)
 create mode 100644 browser/lib/markdown-it-fence.js

diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js
index 5376a773..493b1fc4 100755
--- a/browser/components/MarkdownPreview.js
+++ b/browser/components/MarkdownPreview.js
@@ -738,10 +738,17 @@ export default class MarkdownPreview extends React.Component {
         try {
           const chartConfig = 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'
diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl
index fb30742d..ea46b0b6 100644
--- a/browser/components/markdown.styl
+++ b/browser/components/markdown.styl
@@ -213,10 +213,12 @@ pre
   margin 0 0 1em
   display flex
   line-height 1.4em
-  &.flowchart, &.sequence, &.chart
-    display flex
-    justify-content center
-    background-color white
+  code
+    background-color inherit
+    margin 0
+    padding 0
+    border none
+    border-radius 0
   &.CodeMirror
     height initial
     flex-wrap wrap
@@ -230,12 +232,12 @@ pre
     border none
     border-radius 0
   &>span.filename
-    width 100%
-    border-radius: 5px 0px 0px 0px
-    margin -8px 100% 8px -8px
-    padding 0px 6px
+    margin -8px -7px 8px -8px
+    padding 2px 6px
     background-color #777;
     color white
+    &:empty
+      display none
   &>span.lineNumber
     display none
     font-size 1em
@@ -361,7 +363,7 @@ for name, val in admonition_types
     .admonition.{name}
         @extend $admonition
         border-left-color: val[color]
-    
+
     .admonition.{name}>.admonition-title
         @extend $admonition-title
         border-bottom-color: .1rem solid rgba(val[color], 0.2)
@@ -372,6 +374,18 @@ for name, val in admonition_types
         color: val[color]
         content: val[icon]
 
+pre.fence
+  flex-direction column
+
+  .chart, .flowchart, .mermaid, .sequence
+    display flex
+    justify-content center
+    background-color white
+    max-width 100%
+
+    canvas, svg
+      max-width 100% !important
+
 themeDarkBackground = darken(#21252B, 10%)
 themeDarkText = #f9f9f9
 themeDarkBorder = lighten(themeDarkBackground, 20%)
diff --git a/browser/components/render/MermaidRender.js b/browser/components/render/MermaidRender.js
index bac52b2c..f04d8cd0 100644
--- a/browser/components/render/MermaidRender.js
+++ b/browser/components/render/MermaidRender.js
@@ -2,8 +2,8 @@ import mermaidAPI from 'mermaid'
 
 // fixes bad styling in the mermaid dark theme
 const darkThemeStyling = `
-.loopText tspan { 
-  fill: white; 
+.loopText tspan {
+  fill: white;
 }`
 
 function getRandomInt (min, max) {
@@ -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,14 +21,18 @@ 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'
     mermaidAPI.initialize({
       theme: isDarkTheme ? 'dark' : 'default',
-      themeCSS: isDarkTheme ? darkThemeStyling : ''
+      themeCSS: isDarkTheme ? darkThemeStyling : '',
+      useMaxWidth: false
     })
     mermaidAPI.render(getId(), content, (svgGraph) => {
       element.innerHTML = svgGraph
-      element.style.height = element.attributes.getNamedItem('data-height').value + 'vh'
     })
   } catch (e) {
     console.error(e)
diff --git a/browser/lib/markdown-it-fence.js b/browser/lib/markdown-it-fence.js
new file mode 100644
index 00000000..040ac540
--- /dev/null
+++ b/browser/lib/markdown-it-fence.js
@@ -0,0 +1,130 @@
+'use strict'
+
+module.exports = function (md, renderers, defaultRenderer) {
+  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 = 0
+
+    let match = /^(\w[-\w]*)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/.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 (let 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.js b/browser/lib/markdown.js
index d4bc72e4..40c47aac 100644
--- a/browser/lib/markdown.js
+++ b/browser/lib/markdown.js
@@ -27,32 +27,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' } @@ -150,6 +124,39 @@ class Markdown { this.md.use(require('markdown-it-kbd')) this.md.use(require('markdown-it-admonition')) + this.md.use(require('./markdown-it-fence'), { + chart: token => { + return `
+          ${token.fileName}
+          
${token.content}
+
` + }, + flowchart: token => { + return `
+          ${token.fileName}
+          
${token.content}
+
` + }, + mermaid: token => { + return `
+          ${token.fileName}
+          
${token.content}
+
` + }, + sequence: token => { + return `
+          ${token.fileName}
+          
${token.content}
+
` + } + }, token => { + return `
+        ${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) { From 75a0f4373c355dcd74f51dfe3227922e855f3cf4 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Thu, 13 Sep 2018 11:34:29 +0200 Subject: [PATCH 07/31] fix fileName styling --- browser/components/markdown.styl | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl index ea46b0b6..2780cb9b 100644 --- a/browser/components/markdown.styl +++ b/browser/components/markdown.styl @@ -225,14 +225,8 @@ pre &>code flex 1 overflow-x auto - code - background-color inherit - margin 0 - padding 0 - border none - border-radius 0 &>span.filename - margin -8px -7px 8px -8px + margin -8px 100% 8px -8px padding 2px 6px background-color #777; color white @@ -375,7 +369,7 @@ for name, val in admonition_types content: val[icon] pre.fence - flex-direction column + flex-wrap wrap .chart, .flowchart, .mermaid, .sequence display flex From 0a205f77b07eb19a01771b7a3c92dc2c0b5ae61e Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Thu, 13 Sep 2018 11:46:09 +0200 Subject: [PATCH 08/31] fix diagram's alignment --- browser/components/markdown.styl | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl index 2780cb9b..ea4219af 100644 --- a/browser/components/markdown.styl +++ b/browser/components/markdown.styl @@ -376,6 +376,7 @@ pre.fence justify-content center background-color white max-width 100% + flex-grow 1 canvas, svg max-width 100% !important From 5c186f30a84a75ef5446ee4f885aa20500c1bf30 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Thu, 13 Sep 2018 12:00:08 +0200 Subject: [PATCH 09/31] add yaml format for chart --- browser/components/MarkdownPreview.js | 4 +++- browser/lib/markdown.js | 6 +++++- package.json | 1 + yarn.lock | 7 +++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index 493b1fc4..5ddc7598 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -17,6 +17,7 @@ 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' const { remote } = require('electron') const attachmentManagement = require('../main/lib/dataApi/attachmentManagement') @@ -736,7 +737,8 @@ 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 = '' const canvas = document.createElement('canvas') diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index 40c47aac..87cf86aa 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -126,9 +126,13 @@ class Markdown { this.md.use(require('./markdown-it-fence'), { chart: token => { + if (token.parameters.hasOwnProperty('yaml')) { + token.parameters.format = 'yaml' + } + return `
           ${token.fileName}
-          
${token.content}
+
${token.content}
` }, flowchart: token => { diff --git a/package.json b/package.json index c9e22164..c6267cd7 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "iconv-lite": "^0.4.19", "immutable": "^3.8.1", "js-sequence-diagrams": "^1000000.0.6", + "js-yaml": "^3.12.0", "katex": "^0.9.0", "lodash": "^4.11.1", "lodash-move": "^1.1.1", diff --git a/yarn.lock b/yarn.lock index 4ecfa51b..c155c8d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5254,6 +5254,13 @@ 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.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@~2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-2.0.5.tgz#a25ae6509999e97df278c6719da11bd0687743a8" From 57fadacda0e2ccbe1252ee705415a26c116fa671 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Thu, 13 Sep 2018 12:17:59 +0200 Subject: [PATCH 10/31] update ava snapshots --- tests/lib/snapshots/markdown-test.js.md | 9 ++++++--- tests/lib/snapshots/markdown-test.js.snap | Bin 1724 -> 1730 bytes 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/lib/snapshots/markdown-test.js.md b/tests/lib/snapshots/markdown-test.js.md index ffc3d699..dc7efd31 100644 --- a/tests/lib/snapshots/markdown-test.js.md +++ b/tests/lib/snapshots/markdown-test.js.md @@ -39,9 +39,12 @@ Generated by [AVA](https://ava.li). > Snapshot 1 - `
filename.js2var project = 'boostnote';␊
-    
␊ - ` + `
␊
+            filename.js␊
+            2␊
+            var project = 'boostnote';␊
+    ␊
+          
` ## Markdown.render() should renders markdown correctly diff --git a/tests/lib/snapshots/markdown-test.js.snap b/tests/lib/snapshots/markdown-test.js.snap index fc310cfd28f22b2e7d20fa14c94bd5f9b806b0fd..d814727de0f944aa205e0e2de0a5f953f3a7e9e4 100644 GIT binary patch literal 1730 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 Svl~TT8}l!i*8=N#6951$K|E{# From 4b0dc084265e00da6a5b35dd720396e2eba1f976 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Fri, 14 Sep 2018 00:03:33 +0200 Subject: [PATCH 11/31] highlight code block for chart.js --- browser/components/MarkdownEditor.js | 2 +- browser/components/MarkdownSplitEditor.js | 2 +- browser/lib/markdown-it-fence.js | 4 +- extra_scripts/codemirror/mode/bfm/bfm.js | 107 ++++++++++++++++++++++ lib/main.html | 6 ++ 5 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 extra_scripts/codemirror/mode/bfm/bfm.js diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js index ee80c887..63673583 100644 --- a/browser/components/MarkdownEditor.js +++ b/browser/components/MarkdownEditor.js @@ -250,7 +250,7 @@ class MarkdownEditor extends React.Component { : 'codeEditor--hide' } ref='code' - mode='GitHub Flavored Markdown' + mode='Boost Flavored Markdown' value={value} theme={config.editor.theme} keyMap={config.editor.keyMap} diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index 8fa3cc07..ce518a89 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -145,7 +145,7 @@ class MarkdownSplitEditor extends React.Component { styleName='codeEditor' ref='code' width={this.state.codeEditorWidthInPercent + '%'} - mode='GitHub Flavored Markdown' + mode='Boost Flavored Markdown' value={value} theme={config.editor.theme} keyMap={config.editor.keyMap} diff --git a/browser/lib/markdown-it-fence.js b/browser/lib/markdown-it-fence.js index 040ac540..983ed71e 100644 --- a/browser/lib/markdown-it-fence.js +++ b/browser/lib/markdown-it-fence.js @@ -1,6 +1,8 @@ '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] @@ -66,7 +68,7 @@ module.exports = function (md, renderers, defaultRenderer) { let fileName = '' let firstLineNumber = 0 - let match = /^(\w[-\w]*)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/.exec(params) + let match = paramsRE.exec(params) if (match) { if (match[1]) { langType = match[1] diff --git a/extra_scripts/codemirror/mode/bfm/bfm.js b/extra_scripts/codemirror/mode/bfm/bfm.js new file mode 100644 index 00000000..21a1e25f --- /dev/null +++ b/extra_scripts/codemirror/mode/bfm/bfm.js @@ -0,0 +1,107 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../codemirror/lib/codemirror"), require("../codemirror/mode/gfm/gfm"), require("../codemirror/mode/yaml-frontmatter/yaml-frontmatter")) + else if (typeof define == "function" && define.amd) // AMD + define(["../codemirror/lib/codemirror", "../codemirror/mode/gfm/gfm", "../codemirror/mode/yaml-frontmatter/yaml-frontmatter"], mod) + else // Plain browser env + mod(CodeMirror) +})(function(CodeMirror) { + 'use strict' + + const fencedCodeRE = /^(~~~+|```+)[ \t]*([\w+#-]+)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/ + + function getMode(name, params, config, cm) { + if (!name) { + return null + } + + const parameters = {} + if (params) { + const regex = /(\w[-\w]*)(?:=(?:'(.*?[^\\])?'|"(.*?[^\\])?"|([^'"][^\s]*)))?/g + + let match + while ((match = regex.exec(params))) { + parameters[match[1]] = match[2] || match[3] || match[4] || null + } + } + + if (name === 'chart') { + name = parameters.hasOwnProperty('yaml') ? 'yaml' : 'json' + } + + const found = CodeMirror.findModeByName(name) + if (!found) { + return null + } + + if (CodeMirror.modes.hasOwnProperty(found.mode)) { + const mode = CodeMirror.getMode(config, found.mode) + + return mode.name === 'null' ? null : mode + } else { + CodeMirror.requireMode(found.mode, () => { + cm.setOption('mode', cm.getOption('mode')) + }) + } + } + + CodeMirror.defineMode('bfm', function (config, baseConfig) { + var bfmOverlay = { + startState: function() { + return { + fencedEndRE: null + } + }, + copyState: function(s) { + return { + localMode: s.localMode, + localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null, + + fencedEndRE: s.fencedEndRE + } + }, + token: function(stream, state) { + state.combineTokens = false + + if (state.fencedEndRE && stream.match(state.fencedEndRE)) { + state.fencedEndRE = null + state.localMode = null + state.localState = null + + return null + } + + if (state.localMode) { + return state.localMode.token(stream, state.localState) || '' + } + + const match = stream.match(fencedCodeRE, true) + if (match) { + state.fencedEndRE = new RegExp(match[1] + '+ *$') + + state.localMode = getMode(match[2], match[3], config, stream.lineOracle.doc.cm) + if (state.localMode) { + state.localState = CodeMirror.startState(state.localMode) + } + + return null + } + + state.combineTokens = true + stream.next() + return null + }, + } + + baseConfig.name = 'yaml-frontmatter' + return CodeMirror.overlayMode(CodeMirror.getMode(config, baseConfig), bfmOverlay) + }, 'yaml-frontmatter') + + CodeMirror.defineMIME('text/x-bfm', 'bfm') + + CodeMirror.modeInfo.push({ + name: "Boost Flavored Markdown", + mime: "text/x-bfm", + mode: "bfm" + }) +}) \ No newline at end of file diff --git a/lib/main.html b/lib/main.html index 7366fa04..7a082f3a 100644 --- a/lib/main.html +++ b/lib/main.html @@ -93,8 +93,14 @@ + + + + + + From 44d6374cfe85def481045399f9ea4610bf37419d Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Fri, 14 Sep 2018 16:25:52 +0200 Subject: [PATCH 12/31] remove use of `overlayMode` to be able to detect YAML mode in `chart` code block --- extra_scripts/codemirror/mode/bfm/bfm.js | 63 +++++++++++++++++------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/extra_scripts/codemirror/mode/bfm/bfm.js b/extra_scripts/codemirror/mode/bfm/bfm.js index 21a1e25f..18eadffb 100644 --- a/extra_scripts/codemirror/mode/bfm/bfm.js +++ b/extra_scripts/codemirror/mode/bfm/bfm.js @@ -46,55 +46,80 @@ } CodeMirror.defineMode('bfm', function (config, baseConfig) { - var bfmOverlay = { + baseConfig.name = 'yaml-frontmatter' + const baseMode = CodeMirror.getMode(config, baseConfig) + + return { startState: function() { return { + baseState: CodeMirror.startState(baseMode), + fencedEndRE: null } }, copyState: function(s) { return { - localMode: s.localMode, - localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null, + baseState: CodeMirror.copyState(baseMode, s.baseState), + + fencedMode: s.fencedMode, + fencedState: s.fencedMode ? CodeMirror.copyState(s.fencedMode, s.fencedState) : null, fencedEndRE: s.fencedEndRE } }, token: function(stream, state) { - state.combineTokens = false + const initialPos = stream.pos if (state.fencedEndRE && stream.match(state.fencedEndRE)) { state.fencedEndRE = null - state.localMode = null - state.localState = null + state.fencedMode = null + state.fencedState = null - return null + stream.pos = initialPos + return baseMode.token(stream, state.baseState) } - if (state.localMode) { - return state.localMode.token(stream, state.localState) || '' + if (state.fencedMode) { + return state.fencedMode.token(stream, state.fencedState) } const match = stream.match(fencedCodeRE, true) if (match) { state.fencedEndRE = new RegExp(match[1] + '+ *$') - state.localMode = getMode(match[2], match[3], config, stream.lineOracle.doc.cm) - if (state.localMode) { - state.localState = CodeMirror.startState(state.localMode) + state.fencedMode = getMode(match[2], match[3], config, stream.lineOracle.doc.cm) + if (state.fencedMode) { + state.fencedState = CodeMirror.startState(state.fencedMode) } - return null + stream.pos = initialPos + return baseMode.token(stream, state.baseState) } - state.combineTokens = true - stream.next() - return null + return baseMode.token(stream, state.baseState) }, + electricChars: baseMode.electricChars, + innerMode: function(state) { + if (state.fencedMode) { + return { + mode: state.fencedMode, + state: state.fencedState + } + } else { + return { + mode: baseMode, + state: state.baseState + } + } + }, + blankLine: function(state) { + if (state.fencedMode) { + return state.fencedMode.blankLine && state.fencedMode.blankLine(state.fencedState) + } else { + return baseMode.blankLine(state.baseState) + } + } } - - baseConfig.name = 'yaml-frontmatter' - return CodeMirror.overlayMode(CodeMirror.getMode(config, baseConfig), bfmOverlay) }, 'yaml-frontmatter') CodeMirror.defineMIME('text/x-bfm', 'bfm') From b03c2a1f80ea09a6583294724915dd71388a952b Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Sat, 15 Sep 2018 15:24:59 +0200 Subject: [PATCH 13/31] fix XSS bug --- browser/lib/markdown-it-fence.js | 2 +- browser/lib/markdown-it-sanitize-html.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/lib/markdown-it-fence.js b/browser/lib/markdown-it-fence.js index 040ac540..c2a77a72 100644 --- a/browser/lib/markdown-it-fence.js +++ b/browser/lib/markdown-it-fence.js @@ -120,7 +120,7 @@ module.exports = function (md, renderers, defaultRenderer) { alt: ['paragraph', 'reference', 'blockquote', 'list'] }) - for (let name in renderers) { + for (const name in renderers) { md.renderer.rules[`${name}_fence`] = (tokens, index) => renderers[name](tokens[index]) } diff --git a/browser/lib/markdown-it-sanitize-html.js b/browser/lib/markdown-it-sanitize-html.js index 05e5e7be..fb7267ee 100644 --- a/browser/lib/markdown-it-sanitize-html.js +++ b/browser/lib/markdown-it-sanitize-html.js @@ -14,7 +14,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, From 297c764fe1844cba66e0c03c40602fd41264ca11 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Sat, 15 Sep 2018 18:33:02 +0200 Subject: [PATCH 14/31] - avoid logging to console, the error when the diagram syntax is bad - fix line numbering of code blocks --- browser/components/MarkdownPreview.js | 3 --- browser/components/render/MermaidRender.js | 1 - browser/lib/markdown-it-fence.js | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index 493b1fc4..42c649f9 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -704,7 +704,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 } @@ -725,7 +724,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 } @@ -750,7 +748,6 @@ export default class MarkdownPreview extends React.Component { 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/render/MermaidRender.js b/browser/components/render/MermaidRender.js index f04d8cd0..0ea1960d 100644 --- a/browser/components/render/MermaidRender.js +++ b/browser/components/render/MermaidRender.js @@ -35,7 +35,6 @@ function render (element, content, theme) { 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/markdown-it-fence.js b/browser/lib/markdown-it-fence.js index c2a77a72..983dc45c 100644 --- a/browser/lib/markdown-it-fence.js +++ b/browser/lib/markdown-it-fence.js @@ -64,7 +64,7 @@ module.exports = function (md, renderers, defaultRenderer) { const parameters = {} let langType = '' let fileName = '' - let firstLineNumber = 0 + let firstLineNumber = 1 let match = /^(\w[-\w]*)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/.exec(params) if (match) { From a24f6e80c76b1e7f44e7e76e542d9d0acb29db55 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Sat, 15 Sep 2018 18:57:31 +0200 Subject: [PATCH 15/31] fix styling of `lineNumber` and `filename` with big sized font --- browser/components/markdown.styl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl index ea4219af..2e17a75b 100644 --- a/browser/components/markdown.styl +++ b/browser/components/markdown.styl @@ -206,11 +206,11 @@ 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 code @@ -226,8 +226,8 @@ pre flex 1 overflow-x auto &>span.filename - margin -8px 100% 8px -8px - padding 2px 6px + margin -0.5rem 100% 0.5rem -0.5rem + padding 0.125rem 0.375rem background-color #777; color white &:empty @@ -235,8 +235,8 @@ pre &>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 From fbdc9c9f8d8c6beba8f9263d09f2f81867702557 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Mon, 17 Sep 2018 17:25:37 +0200 Subject: [PATCH 16/31] add `data-line` attribute to fenced blocks --- browser/lib/markdown.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index 089ba5c6..a0892bc6 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -127,31 +127,31 @@ class Markdown { this.md.use(require('./markdown-it-fence'), { chart: token => { - return `
+        return `
           ${token.fileName}
           
${token.content}
` }, flowchart: token => { - return `
+        return `
           ${token.fileName}
           
${token.content}
` }, mermaid: token => { - return `
+        return `
           ${token.fileName}
           
${token.content}
` }, sequence: token => { - return `
+        return `
           ${token.fileName}
           
${token.content}
` } }, token => { - return `
+      return `
         ${token.fileName}
         ${createGutter(token.content, token.firstLineNumber)}
         ${token.content}

From a816c5dc23dfac5a92bd091cecc98e186cbd5779 Mon Sep 17 00:00:00 2001
From: Baptiste Augrain 
Date: Mon, 17 Sep 2018 21:45:59 +0200
Subject: [PATCH 17/31] fix test

---
 tests/lib/snapshots/markdown-test.js.md   |   2 +-
 tests/lib/snapshots/markdown-test.js.snap | Bin 1730 -> 1731 bytes
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/lib/snapshots/markdown-test.js.md b/tests/lib/snapshots/markdown-test.js.md
index dc7efd31..eba9a668 100644
--- a/tests/lib/snapshots/markdown-test.js.md
+++ b/tests/lib/snapshots/markdown-test.js.md
@@ -39,7 +39,7 @@ Generated by [AVA](https://ava.li).
 
 > Snapshot 1
 
-    `
␊
+    `
filename.js2var project = 'boostnote';␊
diff --git a/tests/lib/snapshots/markdown-test.js.snap b/tests/lib/snapshots/markdown-test.js.snap
index d814727de0f944aa205e0e2de0a5f953f3a7e9e4..45218ae26f2fe81dd7286a58cd1410b8d79b622f 100644
GIT binary patch
literal 1731
zcmV;!20ZyeRzVM5BN}E%d-`x+twgyIwz%#%b&oc{F{HKA=y5S~Rpy;?fhG;8acs{+V5GY{yPg+H%6uuE+o5`(HEj
z|Gt^YWS-3YII#KF-Ji}~$>03Ni2ho5zAqy`*EeJ`?#Zt%ym+<$#>M;B-@Y{a?5RFQ
zy*-f0Jojzo*UH_i=f8jVy%+9Zp4rl;sDm3bnT0Mg1~)?!(ic
z*`U1Zdm^)`|H_84lSfr7uXx$M
zJ^ukbqD#_p-X&Vj(ERiIG)BSZSd|OC=@NLQ?CY
z-P^q+D=p8^6!T#%VyknUd8ix;&ir|^DN{BQLfbie_`_|W|nlzNs
z9)%eX2cb@VeK#Cq#&wTXi83YWi25j|BT0W0g%|jYz85Y5S6&3LwU%p4gse00k<;W$
z`$v2l1i*{4ojPEsqv~*EtT^uZ(fGVia6xU@N)z06=n`o?`V*R&a8bgQx4@^X-2xDx
zMMc(a7zOXp{=?CzX1+$M^6uO1&$~2q*2s>$;J8vy8RE-#$eScIQm`Wd_8$t&_Lsq?
z9C?YXRku~Z7J_B4{TN(pM_Z)`g^{GIFwcv8dGRIbFHH|k${y0BL*hTYz0Sl>oH%i|
z2G{l;D)vU!Dq*$goGncr+yA;|9<5U$2w$Jlf^FlH(99WZL&sq?w1=}O=#0FrJ3rG`
z4xl00E)K(rX2WqoQ}8-KIcHpJZ`(}-|97g%xu0>r~UoZ%1%oYmn?O}lKs
zyX-Nu0xPCyK|-UZm#)HewV1AWx)RAMMh&AtQE@``Wy(C6u!P0T?TN9bsMSN%h#`|N
z>_hsXl`|g^9})<+VMT)u2Gf=E@
zUAvo-lHid`QkP(GormtnllTgwZJ$z4^ByO#6)TU~NNYgBniAfc65(1BJv`18M@q4q
zi~km(&80o;(WTz2Z2{aB2To!bSsi*y(7}Z+x>9*J>UxicQcOf)Sly);v-x}x
zc%AtfX^~G11ziteAv@ap)X}qYT<6fHg$_T+P9)z&9H|t|Hvc?Xw{@+3W#SU8gt9{n`I@25#n~n$^)@C88`vmd8N9qUAeMBRGplyfP
zHH)2z=h5aby`aI=ijMh;K&t6X_&|t>ayxQSAy2j8u9z45c9etGp)dy%szc!)SBNmW
zcj2>Fj~zO?``(3X@K-YE&@8N?xpgsOVq7W5%P#t}J@th{&>ZEVK$4X$TWYdz<%Yy&
Z@OL|AuRxwzFY@Y`{{WGCs$r-T008LAU*!M*

literal 1730
zcmV;z20i&fRzVP7=M5}Wo82U(loOWLJNrMr|1~rJ
zzn3&kyH)#c_nymFzJKnm!lfV0_|KJl2Q>M7xJ%Q#Q=goD;QZjlmwx^5#n%?@I6a`K
zpYGPQd%mn*t6n+(!q>07df%_-=I|2!nFe(~|QC%ziG{inSHiu%=E
znznfEL=-xAUHoS4uODuE?d69D74`S@GkLeBy?*rK>C#Kjym!jGw79zGvOB1#@1~z?
z@EO#0Deneu(e566YgffBpc)p~@Mu7)dO=6DR@F}u&tX0>1T$tBi$uT#(XEt<1Vb71
z{)*`qtf7iqY=V`|WLLxOP3?K7)jWq&ecs@ToF+V&}7%tD~mXbtLQld*q
z)RIKMeDwAkV5JCF=n}`^K!etVTh&L$@;d0yWmi=7Qejj_5qGM(D?}Jgnr5TX$Te9k
zVw>c^Z@qBXyHNJk3JX1qptRR=Kad91M%dtT&lLISH|CKfjZIFVyZ31uDW6i*!!Lssn1_F&kS!3X!l!G3`emI2^
zUUb7&C8{we>oe_e2KkyJQC+Z5IdF*C)FTEYAkwYJn!@szidbVA*QPRLqpnan5eMFpra_%`k`BxQq)Y7Lbe<
z4P~@{!;Fu^$e@9-4~{Y8hRDCNpq;Qg&`
z0SM5hBIh;DqJQMz(Rf_9o+LGS_w5UoJsP>&WJg|bTq&pw@r^s=SrVBU*s%}?Hw5Mc
z8(_1pyhOIE+ZJFe;Re`246b#eZBc~cXxden@5h0>_|o*3=Z0rw4{6aM@o#>fy48`6M|XF)QpbX<8#Nk*9&UEIsd&9;Fn2}@bbdL%X061Dq?nh9k3
zg#$<*G;bCl5sc<0Op&zYs@f=<(qDPRuSbPC?U#2c=w~-7p
zNl#kU&1rN6BoSdwvEkBMjRaL)@R)R^92!|HU@8+$56*8gsZHi{<*|`MetaT(h(D$G
zw59Zs&4gfnH%uXyA1#lLY`~NOMz&T6+%qs-_Q9l)&lM&{Mn?J?uyNGwvk%iClF?H*
ztWGZ_CBb8lWG=y|x(xk}r|}iXJDzf1^FAlA6{|PdNP9rxwi5of647=NeLT*WM$3tt
ztN#?C*b0!s)?(WBm5Z2{a92To!X+g*BV(6fahdQy2W>Q0Y_QcOi*Je@R3xk8}?
zyzcyrw#lc4!k&k)m>chZ>gX9cpmS)I2vDb$xrk>*>Gu
zZ5rtEX1%FKw%I}U|2ycv*g@NWbxv2GX|3U~<%qyheF2hsKoB2%q(KPXM>InS+Hr|f
zx7m6!fwq1bMIGi;bUaW5Qp={m>q1PGJCREYdA0+0(}Xy%w-UBb$a$DaT?+rPB81V^
zvmZQh{K!-LuAaRBe;&gw&EgiC53a^cOey7L*+YM!ufA{zTB1A>NV0MjTg~$A+=w^~
Y{$MBUO~~^*Mcx|oZ(NkrbD9$X0Dzc8
Date: Mon, 17 Sep 2018 22:46:20 +0200
Subject: [PATCH 18/31] - add `data-line` attribute to definition lists and
 lists - add tests

---
 browser/lib/markdown-it-deflist.js        |   2 +-
 browser/lib/markdown.js                   |   7 +-
 tests/fixtures/markdowns.js               |  59 ++++++++++++++-
 tests/lib/markdown-test.js                |  20 +++++
 tests/lib/snapshots/markdown-test.js.md   |  88 ++++++++++++++++++----
 tests/lib/snapshots/markdown-test.js.snap | Bin 1724 -> 2265 bytes
 6 files changed, 156 insertions(+), 20 deletions(-)

diff --git a/browser/lib/markdown-it-deflist.js b/browser/lib/markdown-it-deflist.js
index f3c58009..db14c636 100644
--- a/browser/lib/markdown-it-deflist.js
+++ b/browser/lib/markdown-it-deflist.js
@@ -116,7 +116,7 @@ module.exports = function definitionListPlugin (md) {
 
       for (;;) {
         token = state.push('dd_open', 'dd', 1)
-        token.map = itemLines = [ nextLine, 0 ]
+        token.map = itemLines = [ ddLine, 0 ]
 
         pos = contentStart
         max = state.eMarks[ddLine]
diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js
index 6420f215..81a1ed67 100644
--- a/browser/lib/markdown.js
+++ b/browser/lib/markdown.js
@@ -251,9 +251,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/tests/fixtures/markdowns.js b/tests/fixtures/markdowns.js
index 69e335e0..e261f231 100644
--- a/tests/fixtures/markdowns.js
+++ b/tests/fixtures/markdowns.js
@@ -50,11 +50,68 @@ 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.
+`
+
 export default {
   basic,
   codeblock,
   katex,
   checkboxes,
   smartQuotes,
-  breaks
+  breaks,
+  abbrevations,
+  subTexts,
+  supTexts,
+  deflists
 }
diff --git a/tests/lib/markdown-test.js b/tests/lib/markdown-test.js
index 73b68799..e9fb8fc2 100644
--- a/tests/lib/markdown-test.js
+++ b/tests/lib/markdown-test.js
@@ -43,3 +43,23 @@ 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)
+})
diff --git a/tests/lib/snapshots/markdown-test.js.md b/tests/lib/snapshots/markdown-test.js.md
index ffc3d699..b020b098 100644
--- a/tests/lib/snapshots/markdown-test.js.md
+++ b/tests/lib/snapshots/markdown-test.js.md
@@ -25,13 +25,22 @@ Generated by [AVA](https://ava.li).
     `c=pmsqrta2+b2c = pmsqrt{a^2 + b^2}␊
     `
 
+## Markdown.render() should renders abbrevations correctly
+
+> Snapshot 1
+
+    `

abbr

␊ +

The HTML specification
␊ + is maintained by the W3C.

␊ + ` + ## Markdown.render() should renders checkboxes > Snapshot 1 `
    ␊ -
  • Unchecked
  • ␊ -
  • Checked
  • ␊ +
  • Unchecked
  • ␊ +
  • Checked
␊ ` @@ -43,6 +52,37 @@ Generated by [AVA](https://ava.li).
␊ ` +## 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 > Snapshot 1 @@ -52,31 +92,47 @@ Generated by [AVA](https://ava.li).

Docs 📝


Article Archive 📚


Community 🍻

␊ ` +## 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 fc310cfd28f22b2e7d20fa14c94bd5f9b806b0fd..c70ca57b19a7bdb613eea51a604048cf04c608bd 100644 GIT binary patch literal 2265 zcmV;~2qyPIRzV>BV~Yf6{!TdGq-zFMsxP?|bW+6Az3j>JRSKwAHsK-rOT@ z|M)w;Hc3Jx_n;!{dtj^Xz}u{hIdqv)3Q5 zUAy?gWB!fhwS6yn|->aQC17`qbXP{o{$&r=9~}CH2|8n$~*txm&ls zKGpff44e4gZ(qMSrl@bg|DUh?5Px9*uQy6_uQtDn-@G=as2|yb4X((6-;AA0%s zul>>enP?< zQ}=|3;=|=~r_(8IvP2{{DS_W*64=BoFILtbKD!vN2b-sLq~L7EUBa6>fMMTfomS%e zvBL=otwuSuxMhGd=>X@M6Zb|^o1C53ElC2GzxHD0a^l0qr-RCebgO}p$4RU2tcRU8 z;UQz8^40Ff*HBLejDs5O%AR5F%fQ9;4rA8S;41Bs}2=x&|SfRp8Y~{YPbn;BOXT98^ZCal5S>hV! zHbaMoE6VRQK=6~=2*QSvv- zW^m@z*#wHwBgB;j_jtJC)7UGH-KYg8i!4|ADt^3Qxt<_#xrco&!r^w<=BVYd4Ym{Z zvFAKl$%^OP9F^zWV6R4f>{A#V9|qrM0?p}c-(x|Lgt8cCQ&*p#JSKO!E*&QA%Reff zG;^kS(vB`IU24NV^AHsaiCsMC{3bI1ajAan!l_T_*7*(J5}i4+xQ)KJDKkP*sQ%sP-6>x$Y1 zqU97ayWtQ52h9Zw5eXr5P)D0O?3>X2DQbDcP@!-j&`}Vtad8?kp^Y79yg zcwDJX*Hbswc8g$k2g-N!QWQyynD6aU0FT6hl^7>>PH!DHdtr!?)OYY6bPw1GFTZWU-<9* z_TS}x?pK`qHVt)IS>I73J7kdk{|x$HWYEsH;dbJt)@u|qM+A=BixAY4g1~k&^bN;q z&@h6%NNh&%?s&v$+iWB4O}lS~sY3^gE`*9e+{P=}4=a1jM`XZcWqnxI>jpqKfgoz_cIei?VzgVa*Jc3%3 z#{x-KsbQ<0e~=p!hlOs&-hzDMPLb~%Q|3YL(3nmuwryB)@|qnhhD_I_X@VM(j|3HR zWh}ttade(+2y`0rb`qgQ9IhmI1$vBy^QRY~-2!O~#Sw96D{IiQ7=Wt*rf}v3bQjs1 z%JCueCB}UhEm3Htmxv9$c^EV3c9KB1mTGeu_K27*j2@mUKCwLSj2zrT19)mR!mY9u z^<)uhBvGRRRCBf=dsyK~T-nR!C*x=1qj6o*qHxTEcp0kfS$zVMgv_2-8#btPRrQ1= zEbpiak~NTY<p!hUQDdB+>afRf%!`~;Z`Myml<8DEyX9(sbcQVws8kJ(4JA)~o0e$t0w6`i!fv1DH#9&SclB0P?_{E4 z@DT(bL4<(f18*Kff+tbDh~PmC2qGdvPI}T)Jc<5Q-P1cWnSE%YCkLjx=6`(utLm?R zE*XY#tMSd|ZI`cn`^@>$r629&kHve24E1?`lVJoWK015fh2e`YTzmidb8~l`9MaU+ zHXFv>pVfb^U%Bwy7cafM{n{I|_YP_54|f{I;_sV(-6F4k`r+5dKHqZtFFS@b^@FX3 zaq5j@BKEdk{A&5n?`}Ky;)BDQ`hE7@ewSgqa_Hj8$_r1ueImGYYH8bLe^^sR_WcsR z!^S4<-Ow$@UBl-$)%+4_V2Q1OMx<_*Ohg-X^Ee4S77|M`Yl<-;BPNOIWK<*>%BlC( zY`^4esrlt@m~sj;9Z;`n`GjjE(xB1`F>f|lE3!sriz5@WBNL^O>XhkdNu(qdx{^d4 zN%Y$XZ@vmv%3y`ga|{l&XhZsSb8KhP1Rc8I%eq-9jhRSruWtHM#$uOkw_2@2nJy%?M?9iN84%-Jzq~Tn~8-&+Q0K-ARTJuQ|2#*sIIW;@AcwK-y(*S3f zC-O)tBNH>Gqe$TLTkmBqCjmSH>eMjuIhkK^&&OVq@QATUd*^mCYUz~)o^#8`aSZl^ zuwu>{i6`kYm2C@04GSE^*-r?)SQ#brgt$c&EVg;uZ%H5)_J z;O}6k7pU|TS39h+_Z_rzdv=R9sXZOAq+uOyM;?t9w5L-LXcDU$0|#XsbUzN`-6-XW z8@8%Ytr=CHNslwg*9;L&$ztum0p`+xSdai=I(u15Z7~4~X<}4W5!PBL)6z*vwUE-f zVfXedt4gagG|eJd%hc*TXCbNy$yv1EbYyCFM(8^4Ck*dzXM}CK| z>>rM390M=ScJ6?!kE+j+ecf>{ji={*l1u8rR+{9VPnSve(VsM(jEgd^>H_bq)de6x zm&!uWw#(tc{fClq(|Lk4RPWmpEd*5f>tshYIIb0RhWJVkd72122Rj_&=!U?&Xa#KA zS50KSx~&1W7_Wfs$KYBo+8RYDk7c(C3&SK*jW0`ob!KEr-60)1B>weJHkkOy01x<=(_yBdji+Gu5f1`=2zOBP}W=;Tuz0^gLXZrZbB@xN%q$J;GTM_eb7yJO5~!01Ht!Jvc6C8XgBI=Zu?9O+fZK+(aUO|=1#}c>-c^86AOT*-LwtsVoAab#(7H2f- zg!xM3tEGI!^Oek2DXK_fO~n~CQaK7$hB6j&9?Fb$MBP4&ZpEgV?TOp}KRlR2-kkKP2334z#89k;|lHVLwc% zP#mj{jjq5{0Y=@N5O`o==;hHat5_&ajE;`3YQV*!-{%m9J*1+ia2CBmN?L*^0m)s0 zNpu0OGoHm)9`E^7S2Z7U0$Z{EFB|C&C|*}0TvuXX*XWj5#p7aSteU#H^iL7Wok01z zUdq)Z2Go14Er18&z)2K|+o!h-SF*I^Kx%(G*3^w24Xv1o!t}YzsuW743h?^#Gu9=a z8HxuU!g67J^;1XBsQH`2y(=yFL3Sebte{XT-GRxrs}N! zs*!beko*4*`Y(3S`mf$`;$x#T`*j?VSTyG#srw`e!ABa!aQn!13_*K7@tQ6>oer3t zUslfKyHJO=-tQ}%Vp Svl~TT8}l!i*8=N#6951$K|E{# From 002e7ab9ddaf2db8ac6306a082c8269e790b647b Mon Sep 17 00:00:00 2001 From: jacobherrington Date: Sun, 30 Sep 2018 18:26:36 -0500 Subject: [PATCH 19/31] Fix bug caused by poor regex --- browser/main/lib/ConfigManager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 5ffb1bc7..d5bd74f9 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -24,7 +24,7 @@ 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 + Opt + M' : 'Ctrl + M' }, ui: { language: 'en', @@ -195,7 +195,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 } From ffc390d49d012c5472a9194622fa272f365bf1d3 Mon Sep 17 00:00:00 2001 From: jacobherrington Date: Sun, 30 Sep 2018 18:30:34 -0500 Subject: [PATCH 20/31] Reset default hotkey on OS X This shouldn't have been committed it was for testing. This commit resets it to the original hotkey. --- browser/main/lib/ConfigManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index d5bd74f9..72deec5a 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -24,7 +24,7 @@ export const DEFAULT_CONFIG = { amaEnabled: true, hotkey: { toggleMain: OSX ? 'Command + Alt + L' : 'Super + Alt + E', - toggleMode: OSX ? 'Command + Opt + M' : 'Ctrl + M' + toggleMode: OSX ? 'Command + Option + M' : 'Ctrl + M' }, ui: { language: 'en', From b624c9a4d2bddc6d9154bdd7428d85d742ad1870 Mon Sep 17 00:00:00 2001 From: jacobherrington Date: Sun, 30 Sep 2018 22:17:11 -0500 Subject: [PATCH 21/31] Add French translations --- locales/en.json | 1 + locales/fr.json | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/locales/en.json b/locales/en.json index 2c07b119..497d95bf 100644 --- a/locales/en.json +++ b/locales/en.json @@ -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", diff --git a/locales/fr.json b/locales/fr.json index 0523d620..657255f8 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -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 de blog", + "Blog Address": "Adresse de 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", @@ -154,5 +158,9 @@ "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 ! ⚠", "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 de le snippet", + "Snippet prefix": "Préfixe de le snippet" } From 39ce706f3e01914e30e35afd009fea7e820f7f77 Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 1 Oct 2018 09:48:16 -0500 Subject: [PATCH 22/31] Change French translations Following up on PR feedback --- locales/fr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/fr.json b/locales/fr.json index 657255f8..d431c589 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -117,8 +117,8 @@ "Default View": "Vue par défaut", "Compressed View": "Vue compressée", "Search": "Chercher", - "Blog Type": "Type de blog", - "Blog Address": "Adresse de blog", + "Blog Type": "Type du blog", + "Blog Address": "Adresse du blog", "Save": "Sauvegarder", "Auth": "Auth", "Authentication Method": "Méthode d'Authentification", From 52bea8f808f97ea8e23d61182013585558b2dde9 Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 1 Oct 2018 10:30:50 -0500 Subject: [PATCH 23/31] Change French translations Follow up on more PR feedback --- locales/fr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/fr.json b/locales/fr.json index d431c589..ca4231ce 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -161,6 +161,6 @@ "Snippet Default Language": "Langage par défaut d'un snippet", "New Snippet": "Nouveau snippet", "Custom CSS": "CSS personnalisé", - "Snippet name": "Nom de le snippet", - "Snippet prefix": "Préfixe de le snippet" + "Snippet name": "Nom du snippet", + "Snippet prefix": "Préfixe du snippet" } From ced34606732010a7c1d5e670e63c9b27f3126c40 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Mon, 15 Oct 2018 09:04:45 +0200 Subject: [PATCH 24/31] store editor's status in config --- browser/components/MarkdownEditor.js | 11 ++++-- browser/main/Detail/ToggleModeButton.js | 52 ++++++++++++------------- browser/main/lib/ConfigManager.js | 5 ++- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js index 70df16a0..27d0019f 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 @@ -72,9 +73,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 +83,10 @@ class MarkdownEditor extends React.Component { this.refs.preview.focus() } eventEmitter.emit('topbar:togglelockbutton', this.state.status) + + const newConfig = Object.assign({}, this.props.config) + newConfig.editor.delfaultStatus = newStatus + ConfigManager.set(newConfig) }) } } 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 -}) => ( -
-
onClick('SPLIT')}> - -
-
onClick('EDITOR_PREVIEW')}> - -
- {i18n.__('Toggle Mode')} -
-) - -ToggleModeButton.propTypes = { - onClick: PropTypes.func.isRequired, - editorType: PropTypes.string.Required -} - -export default CSSModules(ToggleModeButton, styles) +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 +}) => ( +
+
onClick('SPLIT')}> + +
+
onClick('EDITOR_PREVIEW')}> + +
+ {i18n.__('Toggle Mode')} +
+) + +ToggleModeButton.propTypes = { + onClick: PropTypes.func.isRequired, + editorType: PropTypes.string.Required +} + +export default CSSModules(ToggleModeButton, styles) diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 1727deb8..86aa3f27 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -43,9 +43,10 @@ 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 }, From 148feac43e8cedb51db70c9e297e83b4162c0d30 Mon Sep 17 00:00:00 2001 From: FabioRosado Date: Sat, 20 Oct 2018 15:03:07 +0100 Subject: [PATCH 25/31] Add translation to Portuguese from Portugal --- locales/pt-PT.json | 264 ++++++++++++++++++++++----------------------- 1 file changed, 132 insertions(+), 132 deletions(-) diff --git a/locales/pt-PT.json b/locales/pt-PT.json index 19fe0e94..dcd5b49c 100644 --- a/locales/pt-PT.json +++ b/locales/pt-PT.json @@ -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 creat 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": "LINK 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", + "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": "Unlink", - "Edit": "Edit", - "Delete": "Delete", + "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 de 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! ⚠" } From f18e8c5a3836b49fcd5820c19d8e8df054d4bbc2 Mon Sep 17 00:00:00 2001 From: FabioRosado Date: Fri, 26 Oct 2018 17:25:38 +0100 Subject: [PATCH 26/31] Fix typo, change for suggested term --- locales/pt-PT.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/locales/pt-PT.json b/locales/pt-PT.json index dcd5b49c..94f84a97 100644 --- a/locales/pt-PT.json +++ b/locales/pt-PT.json @@ -5,7 +5,7 @@ "Make a note": "Criar nota", "Ctrl": "Ctrl", "Ctrl(^)": "Ctrl", - "to create a new note": "para creat uma nova nota", + "to create a new note": "para criar uma nova nota", "Toggle Mode": "Alternar Modo", "Trash": "Lixo", "MODIFICATION DATE": "DATA DE MODIFICAÇÃO", @@ -14,7 +14,7 @@ "STORAGE": "ARMAZENAMENTO", "FOLDER": "PASTA", "CREATION DATE": "DATA DE CRIAÇÃO", - "NOTE LINK": "LINK DE NOTA", + "NOTE LINK": "ATALHO DE NOTA", ".md": ".md", ".txt": ".txt", ".html": ".html", @@ -24,7 +24,7 @@ "Add Storage Location": "Adicionar Local de Armazenamento", "Add Folder": "Adicionar Pasta", "Open Storage folder": "Abrir Local de Armazenamento", - "Unlink": "Unlink", + "Unlink": "Remover a ligação", "Edit": "Editar", "Delete": "Apagar", "Interface": "Interface", @@ -90,7 +90,7 @@ "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 de do Boostnote", + "The Boostnote Team": "A Equipa do Boostnote", "Support via OpenCollective": "Suporte via OpenCollective", "Language": "Idioma", "English": "Inglês", From eb61ce2cf20de3f08850385a2d924b08d236b886 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Tue, 6 Nov 2018 09:40:48 +0100 Subject: [PATCH 27/31] use config's local reference --- browser/components/MarkdownEditor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js index 27d0019f..be995a2f 100644 --- a/browser/components/MarkdownEditor.js +++ b/browser/components/MarkdownEditor.js @@ -84,7 +84,7 @@ class MarkdownEditor extends React.Component { } eventEmitter.emit('topbar:togglelockbutton', this.state.status) - const newConfig = Object.assign({}, this.props.config) + const newConfig = Object.assign({}, config) newConfig.editor.delfaultStatus = newStatus ConfigManager.set(newConfig) }) From fd2b438c67afd4e5d0544333c0868167abb45ec6 Mon Sep 17 00:00:00 2001 From: Arcturus Date: Wed, 7 Nov 2018 13:58:47 +0000 Subject: [PATCH 28/31] add language support for european portuguese --- browser/lib/Languages.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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' From 8f290c2a6ddc9787d97d7d1f5b7b21282ae9f84a Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Thu, 8 Nov 2018 06:22:12 +0100 Subject: [PATCH 29/31] rounding paddings --- browser/components/markdown.styl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl index 74fb56de..b7f219b8 100644 --- a/browser/components/markdown.styl +++ b/browser/components/markdown.styl @@ -389,13 +389,13 @@ dt text-align right overflow hidden flex-basis 20% - padding 0.43rem 0.93rem + padding 0.4rem 0.9rem box-sizing border-box dd border-top 1px solid borderColor flex-basis 80% - padding 0.43rem 0.93rem + padding 0.4rem 0.9rem min-height 2.5rem background-color $ui-noteDetail-backgroundColor box-sizing border-box From 48c29dd7d9e645d29ee40bb4161427f56baf5c87 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Thu, 8 Nov 2018 10:01:16 +0100 Subject: [PATCH 30/31] fix turndown --- browser/components/CodeEditor.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 41d71622..b4d10cb3 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -63,6 +63,8 @@ export default class CodeEditor extends React.Component { this.formatTable = () => this.handleFormatTable() this.editorActivityHandler = () => this.handleEditorActivity() + + this.turndownService = new TurndownService() } handleSearch (msg) { @@ -550,6 +552,7 @@ export default class CodeEditor extends React.Component { } const pastedHtml = clipboardData.getData('text/html') + console.log(pastedHtml) if (pastedHtml !== '') { this.handlePasteHtml(e, editor, pastedHtml) } else if (dataTransferItem.type.match('image')) { From 1e3cf6f37423d79e51a77173daed8a1290c14c8a Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Thu, 8 Nov 2018 10:10:45 +0100 Subject: [PATCH 31/31] remove console.log --- browser/components/CodeEditor.js | 1 - 1 file changed, 1 deletion(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index b4d10cb3..a1c74c73 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -552,7 +552,6 @@ export default class CodeEditor extends React.Component { } const pastedHtml = clipboardData.getData('text/html') - console.log(pastedHtml) if (pastedHtml !== '') { this.handlePasteHtml(e, editor, pastedHtml) } else if (dataTransferItem.type.match('image')) {