diff --git a/src/data/core/vnotex.json b/src/data/core/vnotex.json
index 291566c2..2c3fc5d4 100644
--- a/src/data/core/vnotex.json
+++ b/src/data/core/vnotex.json
@@ -124,13 +124,14 @@
"web/js/markdown-it/markdown-it-emoji.min.js",
"web/js/markdown-it/markdown-it-footnote.min.js",
"web/js/markdown-it/markdown-it-front-matter.js",
- "web/js/markdown-it/markdown-it-headinganchor.js",
"web/js/markdown-it/markdown-it-imsize.min.js",
"web/js/markdown-it/markdown-it-sub.min.js",
"web/js/markdown-it/markdown-it-sup.min.js",
"web/js/markdown-it/markdown-it-task-lists.js",
"web/js/markdown-it/markdown-it-texmath.js",
"web/js/markdown-it/markdown-it-inject-linenumbers.js",
+ "web/js/markdown-it/markdownItAnchor.umd.js",
+ "web/js/markdown-it/markdownItTocDoneRight.umd.js",
"web/js/markdownit.js"
],
"styles" : [
diff --git a/src/data/extra/extra.qrc b/src/data/extra/extra.qrc
index 2fade3d1..5fd5928f 100644
--- a/src/data/extra/extra.qrc
+++ b/src/data/extra/extra.qrc
@@ -30,7 +30,8 @@
web/js/markdown-it/markdown-it-emoji.min.js
web/js/markdown-it/markdown-it-footnote.min.js
web/js/markdown-it/markdown-it-front-matter.js
- web/js/markdown-it/markdown-it-headinganchor.js
+ web/js/markdown-it/markdownItAnchor.umd.js
+ web/js/markdown-it/markdownItTocDoneRight.umd.js
web/js/markdown-it/markdown-it-imsize.min.js
web/js/markdown-it/markdown-it-sub.min.js
web/js/markdown-it/markdown-it-sup.min.js
diff --git a/src/data/extra/web/css/globalstyles.css b/src/data/extra/web/css/globalstyles.css
index 088b507e..3a11411f 100644
--- a/src/data/extra/web/css/globalstyles.css
+++ b/src/data/extra/web/css/globalstyles.css
@@ -49,3 +49,35 @@
max-width: 100%;
height: auto;
}
+
+/* Table of Contents */
+.vx-table-of-contents ol {
+ list-style: none;
+}
+
+#vx-content.vx-section-number .vx-table-of-contents > ol > li ol {
+ counter-reset: toc;
+}
+
+#vx-content.vx-section-number .vx-table-of-contents > ol > li ol li {
+ counter-increment: toc;
+}
+
+#vx-content.vx-section-number .vx-table-of-contents > ol > li ol li:before {
+ content: counters(toc, '.') '. ';
+ font-family: cursive;
+}
+
+.vx-header-anchor {
+ visibility: hidden;
+ vertical-align: middle;
+}
+
+.vx-header-anchor::after {
+ content: attr(vx-data-anchor-icon);
+}
+
+#vx-content h1:hover .vx-header-anchor, #vx-content h2:hover .vx-header-anchor, #vx-content h3:hover .vx-header-anchor, #vx-content h4:hover .vx-header-anchor, #vx-content h5:hover .vx-header-anchor, #vx-content h6:hover .vx-header-anchor {
+ visibility: visible;
+ vertical-align: middle;
+}
diff --git a/src/data/extra/web/js/markdown-it/README.md b/src/data/extra/web/js/markdown-it/README.md
index 21f05a42..aea4444a 100644
--- a/src/data/extra/web/js/markdown-it/README.md
+++ b/src/data/extra/web/js/markdown-it/README.md
@@ -3,11 +3,6 @@ v11.0.0
Alex Kocharin
Vitaly Puzrin
-# [markdown-it-headinganchor](https://github.com/adam-p/markdown-it-headinganchor)
-v1.3.0
-Adam Pritchard
-Modified by Le Tan
-
# [markdown-it-task-lists](https://github.com/revin/markdown-it-task-lists)
v2.1.0
Revin Guillen
@@ -52,3 +47,9 @@ Modified by Le Tan
# [markdown-it-xss](https://github.com/yzyeengang/markdown-it-xss)
v1.0.0
+
+# [markdonw-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor)
+v6.0.1
+
+# [markdonw-it-toc-done-right](https://github.com/nagaozen/markdown-it-toc-done-right)
+v4.2.0
diff --git a/src/data/extra/web/js/markdown-it/markdown-it-headinganchor.js b/src/data/extra/web/js/markdown-it/markdown-it-headinganchor.js
deleted file mode 100644
index 93c872d6..00000000
--- a/src/data/extra/web/js/markdown-it/markdown-it-headinganchor.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*! markdown-it-headinganchor 1.2.1 https://github.com//adam-p/markdown-it-headinganchor @license MIT */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.markdownitHeadingAnchor = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o';
- } else {
- anchorToken.content = '';
- }
-
- headingInlineToken.children.push(anchorToken);
- }
-
- // Advance past the inline and heading_close tokens.
- i += 2;
- }
- };
-}
-
-module.exports = function headinganchor_plugin(md, opts) {
- var defaults = {
- anchorClass: 'markdown-it-headinganchor',
- addHeadingID: true,
- addHeadingAnchor: true,
- // Added by Le Tan (github.com/tamlok)
- anchorIcon: '#',
- slugify: slugify,
- headingHook: function(openToken, inlineToken, anchor) {}
- };
- var options = md.utils.assign(defaults, opts);
- md.core.ruler.push('heading_anchors', makeRule(md, options));
-};
-
-},{}]},{},[1])(1)
-});
diff --git a/src/data/extra/web/js/markdown-it/markdownItAnchor.umd.js b/src/data/extra/web/js/markdown-it/markdownItAnchor.umd.js
new file mode 100644
index 00000000..f0346c8e
--- /dev/null
+++ b/src/data/extra/web/js/markdown-it/markdownItAnchor.umd.js
@@ -0,0 +1,2 @@
+!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(n=n||self).markdownItAnchor=e()}(this,function(){var n={false:"push",true:"unshift"},e=Object.prototype.hasOwnProperty,t=function(n,t,r,i){var u=n,o=i;if(r&&e.call(t,u))throw Error("User defined id attribute '"+n+"' is NOT unique. Please fix it in your markdown to continue.");for(;e.call(t,u);)u=n+"-"+o++;return t[u]=!0,u},r=function n(e,r){r=Object.assign({},n.defaults,r),e.core.ruler.push("anchor",function(n){var e,i={},u=n.tokens,o=Array.isArray(r.level)?(e=r.level,function(n){return e.includes(n)}):function(n){return function(e){return e>=n}}(r.level);u.filter(function(n){return"heading_open"===n.type}).filter(function(n){return o(Number(n.tag.substr(1)))}).forEach(function(e){var o=u[u.indexOf(e)+1].children.filter(function(n){return"text"===n.type||"code_inline"===n.type}).reduce(function(n,e){return n+e.content},""),c=e.attrGet("id");c=null==c?t(r.slugify(o),i,!1,r.uniqueSlugStartIndex):t(c,i,!0,r.uniqueSlugStartIndex),e.attrSet("id",c),r.permalink&&r.renderPermalink(c,r,n,u.indexOf(e)),r.callback&&r.callback(e,{slug:c,title:o})})})};return r.defaults={level:1,slugify:function(n){return encodeURIComponent(String(n).trim().toLowerCase().replace(/\s+/g,"-"))},uniqueSlugStartIndex:1,permalink:!1,renderPermalink:function(e,t,r,i){var u,o=[Object.assign(new r.Token("link_open","a",1),{attrs:[].concat(t.permalinkClass?[["class",t.permalinkClass]]:[],[["href",t.permalinkHref(e,r)]],Object.entries(t.permalinkAttrs(e,r)))}),Object.assign(new r.Token("html_block","",0),{content:t.permalinkSymbol}),new r.Token("link_close","a",-1)];t.permalinkSpace&&o[n[!t.permalinkBefore]](Object.assign(new r.Token("text","",0),{content:" "})),(u=r.tokens[i+1].children)[n[t.permalinkBefore]].apply(u,o)},permalinkClass:"header-anchor",permalinkSpace:!0,permalinkSymbol:"¶",permalinkBefore:!1,permalinkHref:function(n){return"#"+n},permalinkAttrs:function(n){return{}}},r});
+//# sourceMappingURL=markdownItAnchor.umd.js.map
diff --git a/src/data/extra/web/js/markdown-it/markdownItTocDoneRight.umd.js b/src/data/extra/web/js/markdown-it/markdownItTocDoneRight.umd.js
new file mode 100644
index 00000000..aaddc06b
--- /dev/null
+++ b/src/data/extra/web/js/markdown-it/markdownItTocDoneRight.umd.js
@@ -0,0 +1,2 @@
+!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).markdownItTocDoneRight=n()}(this,function(){function e(e){return encodeURIComponent(String(e).trim().toLowerCase().replace(/\s+/g,"-"))}function n(e){return String(e).replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}return function(t,r){var l;r=Object.assign({},{placeholder:"(\\$\\{toc\\}|\\[\\[?_?toc_?\\]?\\]|\\$\\)",slugify:e,uniqueSlugStartIndex:1,containerClass:"table-of-contents",containerId:void 0,listClass:void 0,itemClass:void 0,linkClass:void 0,level:1,listType:"ol",format:void 0,callback:void 0},r);var i=new RegExp("^"+r.placeholder+"$","i");t.renderer.rules.tocOpen=function(e,t){var l=Object.assign({},r);return e&&t>=0&&(l=Object.assign(l,e[t].inlineOptions)),""},t.renderer.rules.tocBody=function(e,t){var i=Object.assign({},r);e&&t>=0&&(i=Object.assign(i,e[t].inlineOptions));var o,s={},c=Array.isArray(i.level)?(o=i.level,function(e){return o.includes(e)}):function(e){return function(n){return n>=e}}(i.level);return function e(t){var l=i.listClass?' class="'+n(i.listClass)+'"':"",o=i.itemClass?' class="'+n(i.itemClass)+'"':"",a=i.linkClass?' class="'+n(i.linkClass)+'"':"";if(0===t.c.length)return"";var u="";return(0===t.l||c(t.l))&&(u+="<"+(n(i.listType)+l)+">"),t.c.forEach(function(t){c(t.l)?u+="'+("function"==typeof i.format?i.format(t.n,n):n(t.n))+""+e(t)+"":u+=e(t)}),(0===t.l||c(t.l))&&(u+=""+n(i.listType)+">"),u}(l)},t.core.ruler.push("generateTocAst",function(e){l=function(e){for(var n={l:0,n:"",c:[]},t=[n],r=0,l=e.length;rt[0].l)t[0].c.push(s),t.unshift(s);else if(s.l===t[0].l)t[1].c.push(s),t[0]=s;else{for(;s.l<=t[0].l;)t.shift();t[0].c.push(s),t.unshift(s)}}}return n}(e.tokens),"function"==typeof r.callback&&r.callback(t.renderer.rules.tocOpen()+t.renderer.rules.tocBody()+t.renderer.rules.tocClose(),l)}),t.block.ruler.before("heading","toc",function(e,n,t,r){var l,o=e.src.slice(e.bMarks[n]+e.tShift[n],e.eMarks[n]).split(" ")[0];if(!i.test(o))return!1;if(r)return!0;var s=i.exec(o),c={};if(null!==s&&3===s.length)try{c=JSON.parse(s[2])}catch(e){}return e.line=n+1,(l=e.push("tocOpen","nav",1)).markup="",l.map=[n,e.line],l.inlineOptions=c,(l=e.push("tocBody","",0)).markup="",l.map=[n,e.line],l.inlineOptions=c,l.children=[],(l=e.push("tocClose","nav",-1)).markup="",!0},{alt:["paragraph","reference","blockquote"]})}});
+//# sourceMappingURL=markdownItTocDoneRight.umd.js.map
diff --git a/src/data/extra/web/js/markdownit.js b/src/data/extra/web/js/markdownit.js
index 101e1960..7248227e 100644
--- a/src/data/extra/web/js/markdownit.js
+++ b/src/data/extra/web/js/markdownit.js
@@ -111,7 +111,8 @@ class MarkdownIt extends VxWorker {
this.codeNodesCollected = false;
// Used to deduplicate header Ids.
- this.headerIds = new Set();
+ // One for markdownItAnchor and one for markdownItTocDoneRight.
+ this.headerIds = [new Set(), new Set()];
this.mdit = window.markdownit({
html: this.options.enableHtmlTag,
@@ -140,16 +141,6 @@ class MarkdownIt extends VxWorker {
return /^file:/.test(str) ? true : this.defaultValidateLink(p_url);
};
- this.mdit.use(window.markdownitHeadingAnchor, {
- anchorClass: 'vx-anchor',
- addHeadingID: true,
- addHeadingAnchor: false,
- anchorIcon: '#',
- slugify: (md, str) => {
- return this.generateHeaderId(str);
- },
- });
-
this.mdit.use(window.markdownitTaskLists);
this.mdit.use(window.markdownitSub);
@@ -216,6 +207,30 @@ class MarkdownIt extends VxWorker {
this.mdit.use(window['markdown-it-xss']);
});
}
+
+ this.mdit.use(window.markdownItAnchor, {
+ slugify: (str) => {
+ return this.generateHeaderId(this.headerIds[0], str);
+ },
+ permalink: true,
+ permalinkBefore: false,
+ permalinkClass: 'vx-header-anchor',
+ permalinkSpace: false,
+ // We use CSS:after to add the mark.
+ permalinkSymbol: '',
+ permalinkAttrs: (slug, state) => {
+ return {
+ 'vx-data-anchor-icon': '¶'
+ }
+ }
+ });
+
+ this.mdit.use(window.markdownItTocDoneRight, {
+ slugify: (str) => {
+ return this.generateHeaderId(this.headerIds[1], str);
+ },
+ containerClass: 'vx-table-of-contents'
+ });
}
registerInternal() {
@@ -233,7 +248,8 @@ class MarkdownIt extends VxWorker {
this.frontMatterNode = null;
this.codeNodesStore.clearNodes();
this.codeNodesCollected = false;
- this.headerIds.clear();
+ this.headerIds[0].clear();
+ this.headerIds[1].clear();
if (p_node != this.lastContainerNode) {
this.lastContainerNode = p_node;
@@ -300,15 +316,15 @@ class MarkdownIt extends VxWorker {
return this.codeNodesStore.getNodes(p_langs);
}
- generateHeaderId(p_str) {
+ generateHeaderId(p_headerIds, p_str) {
let idBase = p_str.replace(/\s/g, '-').toLowerCase();
let id = idBase;
let idx = 1;
- while (this.headerIds.has(id)) {
+ while (p_headerIds.has(id)) {
id = idBase + '-' + idx;
++idx;
}
- this.headerIds.add(id);
+ p_headerIds.add(id);
return id;
}
}
diff --git a/src/data/extra/web/js/nodelinemapper.js b/src/data/extra/web/js/nodelinemapper.js
index cd3d357b..f509a907 100644
--- a/src/data/extra/web/js/nodelinemapper.js
+++ b/src/data/extra/web/js/nodelinemapper.js
@@ -38,6 +38,10 @@ class NodeLineMapper {
}
}
+ getHeadingContent(p_node) {
+ return p_node.textContent;
+ }
+
updateHeadingNodes() {
this.headingNodes = this.container.querySelectorAll("h1, h2, h3, h4, h5, h6");
let headings = [];
@@ -45,12 +49,13 @@ class NodeLineMapper {
let regExp = /^\d(?:\.\d)*\.? /;
for (let i = 0; i < this.headingNodes.length; ++i) {
let node = this.headingNodes[i];
+ let headingContent = this.getHeadingContent(node);
headings.push({
- name: node.textContent,
+ name: headingContent,
level: parseInt(node.tagName.substr(1)),
anchor: node.id
});
- if (needSectionNumber && regExp.test(node.textContent)) {
+ if (needSectionNumber && regExp.test(headingContent)) {
needSectionNumber = false;
}
}
diff --git a/src/widgets/notebookexplorer.cpp b/src/widgets/notebookexplorer.cpp
index 94bf9998..6620a006 100644
--- a/src/widgets/notebookexplorer.cpp
+++ b/src/widgets/notebookexplorer.cpp
@@ -293,3 +293,5 @@ void NotebookExplorer::locateNode(Node *p_node)
m_nodeExplorer->setCurrentNode(p_node);
m_nodeExplorer->setFocus();
}
+
+
diff --git a/src/widgets/viewwindow.cpp b/src/widgets/viewwindow.cpp
index 512a3d8d..6bc5d37a 100644
--- a/src/widgets/viewwindow.cpp
+++ b/src/widgets/viewwindow.cpp
@@ -409,7 +409,11 @@ QAction *ViewWindow::addAction(QToolBar *p_toolBar, ViewWindowToolBarHelper::Act
act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
connect(act, &QAction::triggered,
this, [this]() {
- showFindAndReplaceWidget();
+ if (m_findAndReplace && m_findAndReplace->isVisible()) {
+ hideFindAndReplaceWidget();
+ } else {
+ showFindAndReplaceWidget();
+ }
});
break;
}