diff --git a/src/resources/hoedown.js b/src/resources/hoedown.js
index 6a71810f..3f77ca6e 100644
--- a/src/resources/hoedown.js
+++ b/src/resources/hoedown.js
@@ -13,6 +13,9 @@ marked.setOptions({
var updateHtml = function(html) {
placeholder.innerHTML = html;
+
+ insertImageCaption();
+
var codes = document.getElementsByTagName('code');
mermaidIdx = 0;
for (var i = 0; i < codes.length; ++i) {
diff --git a/src/resources/markdown-it.js b/src/resources/markdown-it.js
index a2ecacf1..69c23b1e 100644
--- a/src/resources/markdown-it.js
+++ b/src/resources/markdown-it.js
@@ -167,6 +167,7 @@ var updateText = function(text) {
var html = markdownToHtml(text, needToc);
placeholder.innerHTML = html;
handleToc(needToc);
+ insertImageCaption();
renderMermaid('lang-mermaid');
if (VEnableMathjax) {
try {
diff --git a/src/resources/markdown_template.js b/src/resources/markdown_template.js
index 4ebfaba8..8c1fb6de 100644
--- a/src/resources/markdown_template.js
+++ b/src/resources/markdown_template.js
@@ -14,6 +14,14 @@ if (typeof VEnableMathjax == 'undefined') {
VEnableMathjax = false;
}
+// Add a caption (using alt text) under the image.
+var VImageCenterClass = 'img-center';
+var VImageCaptionClass = 'img-caption';
+var VImagePackageClass = 'img-package';
+if (typeof VEnableImageCaption == 'undefined') {
+ VEnableImageCaption = false;
+}
+
new QWebChannel(qt.webChannelTransport,
function(channel) {
content = channel.objects.content;
@@ -200,3 +208,40 @@ var renderMermaid = function(className) {
}
}
};
+
+var isImageBlock = function(img) {
+ var pn = img.parentNode;
+ return (pn.children.length == 1) && (pn.innerText == '');
+}
+
+// Center the image block and insert the alt text as caption.
+var insertImageCaption = function() {
+ if (!VEnableImageCaption) {
+ return;
+ }
+
+ var imgs = document.getElementsByTagName('img');
+ for (var i = 0; i < imgs.length; ++i) {
+ var img = imgs[i];
+
+ if (!isImageBlock(img)) {
+ continue;
+ }
+
+ // Make the parent img-package.
+ img.parentNode.classList.add(VImagePackageClass);
+
+ // Make it center.
+ img.classList.add(VImageCenterClass);
+
+ if (img.alt == '') {
+ continue;
+ }
+
+ // Add caption.
+ var captionDiv = document.createElement('div');
+ captionDiv.classList.add(VImageCaptionClass);
+ captionDiv.innerText = img.alt;
+ img.insertAdjacentElement('afterend', captionDiv);
+ }
+}
diff --git a/src/resources/marked.js b/src/resources/marked.js
index 5d9c53be..49b1c4a2 100644
--- a/src/resources/marked.js
+++ b/src/resources/marked.js
@@ -125,6 +125,7 @@ var updateText = function(text) {
var html = markdownToHtml(text, needToc);
placeholder.innerHTML = html;
handleToc(needToc);
+ insertImageCaption();
renderMermaid('lang-mermaid');
if (VEnableMathjax) {
try {
diff --git a/src/resources/styles/default.css b/src/resources/styles/default.css
index 1c15f51b..4a2d97f7 100644
--- a/src/resources/styles/default.css
+++ b/src/resources/styles/default.css
@@ -138,13 +138,37 @@ table tr th :first-child, table tr td :first-child {
table tr th :last-child, table tr td :last-child {
margin-bottom: 0;
}
+
div.mermaid-diagram {
overflow-y: hidden;
}
+
pre.mermaid-diagram {
overflow-y: hidden;
}
+.img-package {
+ text-align: center;
+}
+
+img.img-center {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+div.img-caption {
+ min-width: 20%;
+ max-width: 80%;
+ display: inline-block;
+ padding: 10px;
+ margin: 0 auto;
+ border-bottom: 1px solid #c0c0c0;
+ color: #6c6c6c;
+ text-align: center;
+ line-height: 1.5;
+}
+
/* Code below this line is copyright Twitter Inc. */
button,
diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini
index e563cfcc..98a621ac 100644
--- a/src/resources/vnote.ini
+++ b/src/resources/vnote.ini
@@ -33,6 +33,9 @@ enable_preview_image_constraint=true
; Enable image constraint in read mode to constrain the width of the image
enable_image_constraint=true
+; Center image and add the alt text as caption
+enable_image_caption=false
+
[session]
tools_dock_checked=true
diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp
index 65fef234..5c30f326 100644
--- a/src/vconfigmanager.cpp
+++ b/src/vconfigmanager.cpp
@@ -133,6 +133,9 @@ void VConfigManager::initialize()
m_enableImageConstraint = getConfigFromSettings("global",
"enable_image_constraint").toBool();
+
+ m_enableImageCaption = getConfigFromSettings("global",
+ "enable_image_caption").toBool();
}
void VConfigManager::readPredefinedColorsFromSettings()
diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h
index 75156dfe..962a079c 100644
--- a/src/vconfigmanager.h
+++ b/src/vconfigmanager.h
@@ -168,6 +168,9 @@ public:
inline bool getEnableImageConstraint() const;
inline void setEnableImageConstraint(bool p_enabled);
+ inline bool getEnableImageCaption() const;
+ inline void setEnableImageCaption(bool p_enabled);
+
// Get the folder the ini file exists.
QString getConfigFolder() const;
@@ -284,6 +287,9 @@ private:
// Constrain the width of image in read mode.
bool m_enableImageConstraint;
+ // Center image and add the alt text as caption.
+ bool m_enableImageCaption;
+
// The name of the config file in each directory, obsolete.
// Use c_dirConfigFile instead.
static const QString c_obsoleteDirConfigFile;
@@ -757,4 +763,19 @@ inline void VConfigManager::setEnableImageConstraint(bool p_enabled)
m_enableImageConstraint);
}
+inline bool VConfigManager::getEnableImageCaption() const
+{
+ return m_enableImageCaption;
+}
+
+inline void VConfigManager::setEnableImageCaption(bool p_enabled)
+{
+ if (m_enableImageCaption == p_enabled) {
+ return;
+ }
+ m_enableImageCaption = p_enabled;
+ setConfigToSettings("global", "enable_image_caption",
+ m_enableImageCaption);
+}
+
#endif // VCONFIGMANAGER_H
diff --git a/src/vedittab.cpp b/src/vedittab.cpp
index 1a97c380..b9e8a242 100644
--- a/src/vedittab.cpp
+++ b/src/vedittab.cpp
@@ -356,6 +356,10 @@ void VEditTab::setupMarkdownPreview()
"\n";
}
+ if (vconfig.getEnableImageCaption()) {
+ extraFile += "\n";
+ }
+
QString htmlTemplate = VNote::s_markdownTemplate;
htmlTemplate.replace(jsHolder, jsFile);
if (!extraFile.isEmpty()) {
diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp
index ceaf00c6..65fda46a 100644
--- a/src/vmainwindow.cpp
+++ b/src/vmainwindow.cpp
@@ -352,7 +352,7 @@ void VMainWindow::initMarkdownMenu()
initRenderBackgroundMenu(markdownMenu);
- QAction *constrainImageAct = new QAction(tr("Constrain The Width of Images in Read Mode"), this);
+ QAction *constrainImageAct = new QAction(tr("Constrain The Width of Images"), this);
constrainImageAct->setToolTip(tr("Constrain the width of images to the window in read mode (re-open current tabs to make it work)"));
constrainImageAct->setCheckable(true);
connect(constrainImageAct, &QAction::triggered,
@@ -360,6 +360,14 @@ void VMainWindow::initMarkdownMenu()
markdownMenu->addAction(constrainImageAct);
constrainImageAct->setChecked(vconfig.getEnableImageConstraint());
+ QAction *imageCaptionAct = new QAction(tr("Enable Image Caption"), this);
+ imageCaptionAct->setToolTip(tr("Center the images and display the alt text as caption (re-open current tabs to make it work)"));
+ imageCaptionAct->setCheckable(true);
+ connect(imageCaptionAct, &QAction::triggered,
+ this, &VMainWindow::enableImageCaption);
+ markdownMenu->addAction(imageCaptionAct);
+ imageCaptionAct->setChecked(vconfig.getEnableImageCaption());
+
markdownMenu->addSeparator();
QAction *mermaidAct = new QAction(tr("&Mermaid Diagram"), this);
@@ -1316,6 +1324,11 @@ void VMainWindow::enableImageConstraint(bool p_checked)
vnote->updateTemplate();
}
+void VMainWindow::enableImageCaption(bool p_checked)
+{
+ vconfig.setEnableImageCaption(p_checked);
+}
+
void VMainWindow::shortcutHelp()
{
QString locale = VUtils::getLocale();
diff --git a/src/vmainwindow.h b/src/vmainwindow.h
index 3c53dcc2..7b61d452 100644
--- a/src/vmainwindow.h
+++ b/src/vmainwindow.h
@@ -79,6 +79,7 @@ private slots:
void enableImagePreview(bool p_checked);
void enableImagePreviewConstraint(bool p_checked);
void enableImageConstraint(bool p_checked);
+ void enableImageCaption(bool p_checked);
protected:
void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;