From dba154b2c38a923290592a7c686fceb52a9d46fc Mon Sep 17 00:00:00 2001 From: Le Tan Date: Sun, 6 May 2018 21:36:22 +0800 Subject: [PATCH] support specifying image size in preview --- src/resources/docs/markdown_guide_en.md | 13 +++- src/resources/docs/markdown_guide_zh.md | 13 +++- src/utils/vutils.cpp | 5 +- src/utils/vutils.h | 8 ++- src/vpreviewmanager.cpp | 80 +++++++++++++++++-------- src/vpreviewmanager.h | 37 ++++++++++-- 6 files changed, 121 insertions(+), 35 deletions(-) diff --git a/src/resources/docs/markdown_guide_en.md b/src/resources/docs/markdown_guide_en.md index 6aa23260..157de232 100644 --- a/src/resources/docs/markdown_guide_en.md +++ b/src/resources/docs/markdown_guide_en.md @@ -73,7 +73,15 @@ Notice that the sequence number is irrelevant. Markdown will change the sequence ### Images and Links ```md -![Image Alt Text](/url/to/images.png) +![Image Alt Text](/url/to/image.png "Optional Text") + +![Image Alt Text](/url/to/image.png "Image specified with width and height" =800x600) + +![Image Alt Text](/url/to/image.png =800x600) + +![Image Alt Text](/url/to/image.png "Image specified with width" =800x) + +![Image Alt Text](/url/to/image.png "Image specified with height" =x600) [Link Text](/url/of/the/link) ``` @@ -81,6 +89,7 @@ Notice that the sequence number is irrelevant. Markdown will change the sequence **Notes**: - It is not recommended to use image links in reference format. VNote will not preview those images. +- Specifying size of image is supported only in **markdown-it**. ### Blockquotes ```md @@ -164,6 +173,8 @@ VNote also supports displayed mathematics via fenced code block with language `m Here is a `inline code`. ``` +To insert one `` ` ``, you need to use two `` ` `` to enclose it, such as ``` `` ` `` ```. To insert two `` ` ``, you need to use three `` ` ``. + ### Strikethrough ```md Here is a ~~text~~ with strikethrough. diff --git a/src/resources/docs/markdown_guide_zh.md b/src/resources/docs/markdown_guide_zh.md index 429e8477..22aaabb0 100644 --- a/src/resources/docs/markdown_guide_zh.md +++ b/src/resources/docs/markdown_guide_zh.md @@ -74,7 +74,15 @@ __This text will be bold__ ### 图片和链接 ```md -![Image Alt Text](/url/to/images.png) +![Image Alt Text](/url/to/image.png "Optional Text") + +![Image Alt Text](/url/to/image.png "Image specified with width and height" =800x600) + +![Image Alt Text](/url/to/image.png =800x600) + +![Image Alt Text](/url/to/image.png "Image specified with width" =800x) + +![Image Alt Text](/url/to/image.png "Image specified with height" =x600) [Link Text](/url/of/the/link) ``` @@ -82,6 +90,7 @@ __This text will be bold__ **注意**: - VNote不推荐使用参考式的图片链接。VNote不会预览这些图片。 +- 声明图片尺寸只在 **markdown-it** 中支持。 ### 块引用 ```md @@ -165,6 +174,8 @@ VNote也可以使用标明语言`mathjax`的代码块来实现块公式。使用 Here is a `inline code`. ``` +如果想输入一个 `` ` ``,需要使用两个 `` ` `` 来括住它,例如 ``` `` ` `` ```。 要输入两个 `` ` ``,则需要使用三个 `` ` ``。 + ### 删除线 ```md Here is a ~~text~~ with strikethrough. diff --git a/src/utils/vutils.cpp b/src/utils/vutils.cpp index 9f0cff2d..0541c2f5 100644 --- a/src/utils/vutils.cpp +++ b/src/utils/vutils.cpp @@ -37,7 +37,10 @@ extern VConfigManager *g_config; QVector> VUtils::s_availableLanguages; -const QString VUtils::c_imageLinkRegExp = QString("\\!\\[([^\\]]*)\\]\\(([^\\)\"]+)\\s*(\"(\\\\.|[^\"\\)])*\")?\\s*\\)"); +const QString VUtils::c_imageLinkRegExp = QString("\\!\\[([^\\]]*)\\]\\(([^\\)\"'\\s]+)\\s*" + "((\"[^\"\\)\\n]*\")|('[^'\\)\\n]*'))?\\s*" + "(=(\\d*)x(\\d*))?\\s*" + "\\)"); const QString VUtils::c_imageTitleRegExp = QString("[\\w\\(\\)@#%\\*\\-\\+=\\?<>\\,\\.\\s]*"); diff --git a/src/utils/vutils.h b/src/utils/vutils.h index 05b7263a..468fbe56 100644 --- a/src/utils/vutils.h +++ b/src/utils/vutils.h @@ -328,12 +328,16 @@ public: static QPixmap pixmapFromFile(const QString &p_filePath); // Regular expression for image link. - // ![image title]( http://github.com/tamlok/vnote.jpg "alt \" text" ) + // ![image title]( http://github.com/tamlok/vnote.jpg "alt text" =200x100) // Captured texts (need to be trimmed): // 1. Image Alt Text (Title); // 2. Image URL; - // 3. Image Optional Title with double quotes; + // 3. Image Optional Title with double quotes or quotes; // 4. Unused; + // 5. Unused; + // 6. Unused; + // 7. Width; + // 8. Height; static const QString c_imageLinkRegExp; // Regular expression for image title. diff --git a/src/vpreviewmanager.cpp b/src/vpreviewmanager.cpp index b5484846..38a15913 100644 --- a/src/vpreviewmanager.cpp +++ b/src/vpreviewmanager.cpp @@ -158,31 +158,31 @@ void VPreviewManager::fetchImageLinksFromRegions(QVector p_image || isAllSpaces(text, reg.m_endPos - blockStart, blockEnd - blockStart))) { // Image block. info.m_isBlock = true; - info.m_linkUrl = fetchImagePathToPreview(text, info.m_linkShortUrl); + fetchImageInfoToPreview(text, info); } else { // Inline image. info.m_isBlock = false; - info.m_linkUrl = fetchImagePathToPreview(text.mid(reg.m_startPos - blockStart, - reg.m_endPos - reg.m_startPos), - info.m_linkShortUrl); + fetchImageInfoToPreview(text.mid(reg.m_startPos - blockStart, + reg.m_endPos - reg.m_startPos), + info); } - if (info.m_linkUrl.isEmpty()) { + if (info.m_linkUrl.isEmpty() || info.m_linkShortUrl.isEmpty()) { continue; } p_imageLinks.append(info); - qDebug() << "image region" << i - << info.m_startPos << info.m_endPos << info.m_blockNumber - << info.m_linkShortUrl << info.m_linkUrl << info.m_isBlock; + qDebug() << "image region" << i << info.toString(); } } -QString VPreviewManager::fetchImageUrlToPreview(const QString &p_text) +QString VPreviewManager::fetchImageUrlToPreview(const QString &p_text, int &p_width, int &p_height) { QRegExp regExp(VUtils::c_imageLinkRegExp); + p_width = p_height = -1; + int index = regExp.indexIn(p_text); if (index == -1) { return QString(); @@ -193,30 +193,48 @@ QString VPreviewManager::fetchImageUrlToPreview(const QString &p_text) return QString(); } - return regExp.capturedTexts()[2].trimmed(); + QString tmp(regExp.cap(7)); + if (!tmp.isEmpty()) { + p_width = tmp.toInt(); + if (p_width <= 0) { + p_width = -1; + } + } + + tmp = regExp.cap(8); + if (!tmp.isEmpty()) { + p_height = tmp.toInt(); + if (p_height <= 0) { + p_height = -1; + } + } + + return regExp.cap(2).trimmed(); } -QString VPreviewManager::fetchImagePathToPreview(const QString &p_text, QString &p_url) +void VPreviewManager::fetchImageInfoToPreview(const QString &p_text, ImageLinkInfo &p_info) { - p_url = fetchImageUrlToPreview(p_text); - if (p_url.isEmpty()) { - return p_url; + QString surl = fetchImageUrlToPreview(p_text, p_info.m_width, p_info.m_height); + p_info.m_linkShortUrl = surl; + if (surl.isEmpty()) { + p_info.m_linkUrl = surl; + return; } const VFile *file = m_editor->getFile(); QString imagePath; - QFileInfo info(file->fetchBasePath(), p_url); + QFileInfo info(file->fetchBasePath(), surl); if (info.exists()) { if (info.isNativePath()) { // Local file. imagePath = QDir::cleanPath(info.absoluteFilePath()); } else { - imagePath = p_url; + imagePath = surl; } } else { - QString decodedUrl(p_url); + QString decodedUrl(surl); VUtils::decodeUrl(decodedUrl); QFileInfo dinfo(file->fetchBasePath(), decodedUrl); if (dinfo.exists()) { @@ -224,10 +242,10 @@ QString VPreviewManager::fetchImagePathToPreview(const QString &p_text, QString // Local file. imagePath = QDir::cleanPath(dinfo.absoluteFilePath()); } else { - imagePath = p_url; + imagePath = surl; } } else { - QUrl url(p_url); + QUrl url(surl); if (url.isLocalFile()) { imagePath = url.toLocalFile(); } else { @@ -236,14 +254,16 @@ QString VPreviewManager::fetchImagePathToPreview(const QString &p_text, QString } } - return imagePath; + p_info.m_linkUrl = imagePath; } QString VPreviewManager::imageResourceName(const ImageLinkInfo &p_link) { - QString name = p_link.m_linkShortUrl; - if (m_editor->containsImage(name) - || name.isEmpty()) { + // Add size info to the name. + QString name = QString("%1_%2_%3").arg(p_link.m_linkShortUrl) + .arg(p_link.m_width) + .arg(p_link.m_height); + if (m_editor->containsImage(name)) { return name; } @@ -263,7 +283,19 @@ QString VPreviewManager::imageResourceName(const ImageLinkInfo &p_link) return QString(); } - m_editor->addImage(name, image); + // Resize the image. + if (p_link.m_width > 0) { + if (p_link.m_height > 0) { + m_editor->addImage(name, image.scaled(p_link.m_width, p_link.m_height)); + } else { + m_editor->addImage(name, image.scaledToWidth(p_link.m_width)); + } + } else if (p_link.m_height > 0) { + m_editor->addImage(name, image.scaledToHeight(p_link.m_height)); + } else { + m_editor->addImage(name, image); + } + return name; } diff --git a/src/vpreviewmanager.h b/src/vpreviewmanager.h index 2e3d7cf3..ff273026 100644 --- a/src/vpreviewmanager.h +++ b/src/vpreviewmanager.h @@ -101,7 +101,9 @@ private: m_blockPos(-1), m_blockNumber(-1), m_padding(0), - m_isBlock(false) + m_isBlock(false), + m_width(-1), + m_height(-1) { } @@ -115,10 +117,28 @@ private: m_blockPos(p_blockPos), m_blockNumber(p_blockNumber), m_padding(p_padding), - m_isBlock(false) + m_isBlock(false), + m_width(-1), + m_height(-1) { } + QString toString() const + { + return QString("ImageLinkInfo [%1,%2) block(%3,%4) padding %5 " + "short %6 url %7 isBlock %8 width %9 height %10") + .arg(m_startPos) + .arg(m_endPos) + .arg(m_blockNumber) + .arg(m_blockPos) + .arg(m_padding) + .arg(m_linkShortUrl) + .arg(m_linkUrl) + .arg(m_isBlock) + .arg(m_width) + .arg(m_height); + } + int m_startPos; int m_endPos; @@ -140,6 +160,12 @@ private: // Whether it is an image block. bool m_isBlock; + + // Image width, -1 for not specified. + int m_width; + + // Image height, -1 for not specified. + int m_height; }; // Start to preview images according to image links. @@ -151,11 +177,10 @@ private: QVector &p_imageLinks); // Fetch the image link's URL if there is only one link. - QString fetchImageUrlToPreview(const QString &p_text); + QString fetchImageUrlToPreview(const QString &p_text, int &p_width, int &p_height); - // Fetch teh image's full path if there is only one image link. - // @p_url: contains the short URL in ![](). - QString fetchImagePathToPreview(const QString &p_text, QString &p_url); + // Fetch the image's full path and size. + void fetchImageInfoToPreview(const QString &p_text, ImageLinkInfo &p_info); // Update the preview info of related blocks according to @p_imageLinks. void updateBlockPreviewInfo(TS p_timeStamp, const QVector &p_imageLinks);