Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion browser/components/MarkdownPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import yaml from 'js-yaml'
import context from 'browser/lib/context'
import i18n from 'browser/lib/i18n'
import fs from 'fs'
import { render } from 'react-dom'
import Carousel from 'react-image-carousel'

const { remote, shell } = require('electron')
const attachmentManagement = require('../main/lib/dataApi/attachmentManagement')
Expand All @@ -39,7 +41,8 @@ const appPath = fileUrl(
)
const CSS_FILES = [
`${appPath}/node_modules/katex/dist/katex.min.css`,
`${appPath}/node_modules/codemirror/lib/codemirror.css`
`${appPath}/node_modules/codemirror/lib/codemirror.css`,
`${appPath}/node_modules/react-image-carousel/lib/css/main.min.css`
]

function buildStyle (
Expand Down Expand Up @@ -795,6 +798,34 @@ export default class MarkdownPreview extends React.Component {
mermaidRender(el, htmlTextHelper.decodeEntities(el.innerHTML), theme)
}
)

_.forEach(
this.refs.root.contentWindow.document.querySelectorAll('.gallery'),
el => {
const images = el.innerHTML.split(/\n/g).filter(i => i.length > 0)
el.innerHTML = ''

const height = el.attributes.getNamedItem('data-height')
if (height && height.value !== 'undefined') {
el.style.height = height.value + 'vh'
}

let autoplay = el.attributes.getNamedItem('data-autoplay')
if (autoplay && autoplay.value !== 'undefined') {
autoplay = parseInt(autoplay.value, 10) || 0
} else {
autoplay = 0
}

render(
<Carousel
images={images}
autoplay={autoplay}
/>,
el
)
}
)
}

focus () {
Expand Down
54 changes: 54 additions & 0 deletions browser/components/markdown.styl
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,26 @@ pre.fence
canvas, svg
max-width 100% !important

.gallery
width 100%
height 50vh

.carousel
.carousel-main img
min-width auto
max-width 100%
min-height auto
max-height 100%

.carousel-footer::-webkit-scrollbar-corner
background-color transparent

.carousel-main, .carousel-footer
background-color $ui-noteDetail-backgroundColor
.prev, .next
color $ui-text-color
background-color $ui-tag-backgroundColor

themeDarkBackground = darken(#21252B, 10%)
themeDarkText = #f9f9f9
themeDarkBorder = lighten(themeDarkBackground, 20%)
Expand Down Expand Up @@ -475,6 +495,14 @@ body[data-theme="dark"]
border-color themeDarkBorder
background-color themeDarkPreview

pre.fence
.gallery
.carousel-main, .carousel-footer
background-color $ui-dark-noteDetail-backgroundColor
.prev, .next
color $ui-dark-text-color
background-color $ui-dark-tag-backgroundColor

themeSolarizedDarkTableOdd = $ui-solarized-dark-noteDetail-backgroundColor
themeSolarizedDarkTableEven = darken($ui-solarized-dark-noteDetail-backgroundColor, 10%)
themeSolarizedDarkTableHead = themeSolarizedDarkTableEven
Expand Down Expand Up @@ -510,6 +538,14 @@ body[data-theme="solarized-dark"]
border-color themeDarkBorder
background-color $ui-solarized-dark-noteDetail-backgroundColor

pre.fence
.gallery
.carousel-main, .carousel-footer
background-color $ui-solarized-dark-noteDetail-backgroundColor
.prev, .next
color $ui-solarized-dark-button--active-color
background-color $ui-solarized-dark-button-backgroundColor

themeMonokaiTableOdd = $ui-monokai-noteDetail-backgroundColor
themeMonokaiTableEven = darken($ui-monokai-noteDetail-backgroundColor, 10%)
themeMonokaiTableHead = themeMonokaiTableEven
Expand Down Expand Up @@ -538,6 +574,7 @@ body[data-theme="monokai"]
border-right solid 1px themeMonokaiTableBorder
kbd
background-color themeDarkBackground

dl
border-color themeDarkBorder
background-color themeMonokaiTableHead
Expand All @@ -547,6 +584,14 @@ body[data-theme="monokai"]
border-color themeDarkBorder
background-color $ui-monokai-noteDetail-backgroundColor

pre.fence
.gallery
.carousel-main, .carousel-footer
background-color $ui-monokai-noteDetail-backgroundColor
.prev, .next
color $ui-monokai-button--active-color
background-color $ui-monokai-button-backgroundColor

themeDraculaTableOdd = $ui-dracula-noteDetail-backgroundColor
themeDraculaTableEven = darken($ui-dracula-noteDetail-backgroundColor, 10%)
themeDraculaTableHead = themeDraculaTableEven
Expand Down Expand Up @@ -575,6 +620,7 @@ body[data-theme="dracula"]
border-right solid 1px themeDraculaTableBorder
kbd
background-color themeDarkBackground

dl
border-color themeDarkBorder
background-color themeDraculaTableHead
Expand All @@ -583,3 +629,11 @@ body[data-theme="dracula"]
dd
border-color themeDarkBorder
background-color $ui-dracula-noteDetail-backgroundColor

pre.fence
.gallery
.carousel-main, .carousel-footer
background-color $ui-dracula-noteDetail-backgroundColor
.prev, .next
color $ui-dracula-button--active-color
background-color $ui-dracula-button-backgroundColor
15 changes: 15 additions & 0 deletions browser/lib/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,21 @@ class Markdown {
<div class="flowchart" data-height="${token.parameters.height}">${token.content}</div>
</pre>`
},
gallery: token => {
const content = token.content.split('\n').slice(0, -1).map(line => {
const match = /!\[[^\]]*]\(([^\)]*)\)/.exec(line)
if (match) {
return match[1]
} else {
return line
}
}).join('\n')

return `<pre class="fence" data-line="${token.map[0]}">
<span class="filename">${token.fileName}</span>
<div class="gallery" data-autoplay="${token.parameters.autoplay}" data-height="${token.parameters.height}">${content}</div>
</pre>`
},
mermaid: token => {
return `<pre class="fence" data-line="${token.map[0]}">
<span class="filename">${token.fileName}</span>
Expand Down
2 changes: 1 addition & 1 deletion browser/main/lib/dataApi/attachmentManagement.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ function migrateAttachments (markdownContent, storagePath, noteKey) {
* @returns {String} postprocessed HTML in which all :storage references are mapped to the actual paths.
*/
function fixLocalURLS (renderedHTML, storagePath) {
return renderedHTML.replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '.*?"', 'g'), function (match) {
return renderedHTML.replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '(?:\\\/|%5C)[\\w.]+', 'g'), function (match) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add some comment explaining the regex?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've undone the change because I don't remember why I've changed it. And it works with the original one...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, now, I understand why 😁

![#5.jpg](:storage/3b6f8bd6-4edd-4b15-96e0-eadc4475b564/fad71156.jpg)

generates

<p data-line="1"><img src=":storage/3b6f8bd6-4edd-4b15-96e0-eadc4475b564/fad71156.jpg" alt="#5.jpg" /></p>
```gallery(30h)
![#5.jpg](:storage/3b6f8bd6-4edd-4b15-96e0-eadc4475b564/fad71156.jpg)
```

generates

<pre class="fence" data-line="1">
          <span class="filename"></span>
          <div class="gallery" data-autoplay="undefined" data-height="20">:storage/3b6f8bd6-4edd-4b15-96e0-eadc4475b564/fad71156.jpg</div>
</pre>

new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '.*?"', 'g') will only match the first image due to the need of the closing ".
new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER + '(?:\\\/|%5C)[\\w.]+', 'g') will match both images. The \\\/ is for posix systems and %5C is for windows.
It might need further testing on windows.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't you use the PATH_SEPARATORS variable which is defined at the top of the file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PATH_SEPARATORS 's value is /\\ so it can't be used.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you, at least, use path.win32.sep and path.posix.sep? That would make clearer what the RegExp means..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path.win32.sep is \\ which is far from the needed %5C

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then i am wondering whether you really need your %5C i mean: it dosen't appear everywhere else in the attachment-management, does it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the URI encoding of \. After I don't know where it's been done.

var encodedPathSeparators = new RegExp(mdurl.encode(path.win32.sep) + '|' + mdurl.encode(path.posix.sep), 'g')
return match.replace(encodedPathSeparators, path.sep).replace(new RegExp('/?' + STORAGE_FOLDER_PLACEHOLDER, 'g'), 'file:///' + path.join(storagePath, DESTINATION_FOLDER))
})
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,10 @@
"react-codemirror": "^0.3.0",
"react-debounce-render": "^4.0.1",
"react-dom": "^15.0.2",
"react-image-carousel": "^2.0.18",
"react-redux": "^4.4.5",
"react-sortable-hoc": "^0.6.7",
"react-transition-group": "^2.5.0",
"redux": "^3.5.2",
"sander": "^0.5.1",
"sanitize-html": "^1.18.2",
Expand Down
38 changes: 38 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,10 @@ doctrine@^2.0.0, doctrine@^2.0.2:
dependencies:
esutils "^2.0.2"

dom-helpers@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6"

dom-serializer@0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
Expand Down Expand Up @@ -5319,6 +5323,10 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"

"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"

js-yaml@^3.10.0, js-yaml@^3.5.1, js-yaml@^3.7.0:
version "3.11.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef"
Expand Down Expand Up @@ -5800,6 +5808,12 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3
dependencies:
js-tokens "^3.0.0"

loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
dependencies:
js-tokens "^3.0.0 || ^4.0.0"

loud-rejection@^1.0.0, loud-rejection@^1.2.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
Expand Down Expand Up @@ -7242,6 +7256,13 @@ prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8,
loose-envify "^1.3.1"
object-assign "^4.1.1"

prop-types@^15.6.2:
version "15.6.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
dependencies:
loose-envify "^1.3.1"
object-assign "^4.1.1"

proxy-addr@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341"
Expand Down Expand Up @@ -7421,13 +7442,21 @@ react-dom@^15.0.2:
object-assign "^4.1.0"
prop-types "^15.5.10"

react-image-carousel@^2.0.18:
version "2.0.18"
resolved "https://registry.yarnpkg.com/react-image-carousel/-/react-image-carousel-2.0.18.tgz#5868ea09bd9cca09c4467d3d02695cd4e7792f28"

react-input-autosize@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-1.2.0.tgz#87241071159f742123897691da6796ec33b57d05"
dependencies:
create-react-class "^15.5.2"
prop-types "^15.5.8"

react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"

react-proxy@^1.1.7:
version "1.1.8"
resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-1.1.8.tgz#9dbfd9d927528c3aa9f444e4558c37830ab8c26a"
Expand Down Expand Up @@ -7493,6 +7522,15 @@ react-transform-hmr@^1.0.3:
global "^4.3.0"
react-proxy "^1.1.7"

react-transition-group@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.5.0.tgz#70bca0e3546102c4dc5cf3f5f57f73447cce6874"
dependencies:
dom-helpers "^3.3.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-lifecycles-compat "^3.0.4"

react@^15.5.4:
version "15.6.2"
resolved "https://registry.yarnpkg.com/react/-/react-15.6.2.tgz#dba0434ab439cfe82f108f0f511663908179aa72"
Expand Down