From 17645b2d96c35089e3ce16fa6194e8b2974745cd Mon Sep 17 00:00:00 2001 From: RunDevelopment Date: Fri, 29 Nov 2019 18:43:19 +0100 Subject: [PATCH 1/4] Line Numbers: Improved resize performance --- plugins/line-numbers/prism-line-numbers.js | 85 +++++++++++++++---- .../line-numbers/prism-line-numbers.min.js | 2 +- 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/plugins/line-numbers/prism-line-numbers.js b/plugins/line-numbers/prism-line-numbers.js index 7ab1dc046b..b3b6bde751 100644 --- a/plugins/line-numbers/prism-line-numbers.js +++ b/plugins/line-numbers/prism-line-numbers.js @@ -17,16 +17,23 @@ var NEW_LINE_EXP = /\n(?!$)/g; /** - * Resizes line numbers spans according to height of line of code - * @param {Element} element
 element
+	 * Resizes the given elements.
+	 *
+	 * @param {HTMLElement[]} elements
 	 */
-	var _resizeElement = function (element) {
-		var codeStyles = getStyles(element);
-		var whiteSpace = codeStyles['white-space'];
+	function resizeElements(elements) {
+		elements = elements.filter(function (e) {
+			var codeStyles = getStyles(e);
+			var whiteSpace = codeStyles['white-space'];
+			return whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line';
+		});
+
+		if (elements.length == 0) {
+			return;
+		}
 
-		if (whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line') {
+		var infos = elements.map(function (element) {
 			var codeElement = element.querySelector('code');
-			var lineNumbersWrapper = element.querySelector('.line-numbers-rows');
 			var lineNumberSizer = element.querySelector('.line-numbers-sizer');
 			var codeLines = codeElement.textContent.split(NEW_LINE_EXP);
 
@@ -37,18 +44,64 @@
 				codeElement.appendChild(lineNumberSizer);
 			}
 
+			lineNumberSizer.innerHTML = '0';
 			lineNumberSizer.style.display = 'block';
 
-			codeLines.forEach(function (line, lineNumber) {
-				lineNumberSizer.textContent = line || '\n';
-				var lineSize = lineNumberSizer.getBoundingClientRect().height;
-				lineNumbersWrapper.children[lineNumber].style.height = lineSize + 'px';
+			var oneLinerHeight = lineNumberSizer.getBoundingClientRect().height;
+			lineNumberSizer.innerHTML = '';
+
+			return {
+				element: element,
+				lines: codeLines,
+				lineHeights: [],
+				oneLinerHeight: oneLinerHeight,
+				sizer: lineNumberSizer,
+			};
+		});
+
+		infos.forEach(function (info) {
+			var lineNumberSizer = info.sizer;
+			var lines = info.lines;
+			var lineHeights = info.lineHeights;
+			var oneLinerHeight = info.oneLinerHeight;
+
+			lineHeights[lines.length - 1] = undefined;
+			lines.forEach(function (line, index) {
+				if (line && line.length > 1) {
+					var e = lineNumberSizer.appendChild(document.createElement('span'));
+					e.style.display = 'block';
+					e.textContent = line;
+					lineNumberSizer.appendChild(document.createTextNode('\n'));
+				} else {
+					lineHeights[index] = oneLinerHeight;
+				}
 			});
+		});
+
+		infos.forEach(function (info) {
+			var lineNumberSizer = info.sizer;
+			var lineHeights = info.lineHeights;
+
+			var childIndex = 0;
+			for (var i = 0; i < lineHeights.length; i++) {
+				if (lineHeights[i] === undefined) {
+					lineHeights[i] = lineNumberSizer.children[childIndex++].getBoundingClientRect().height;
+				}
+			}
+		});
+
+		infos.forEach(function (info) {
+			var lineNumberSizer = info.sizer;
+			var wrapper = info.element.querySelector('.line-numbers-rows');
 
-			lineNumberSizer.textContent = '';
 			lineNumberSizer.style.display = 'none';
-		}
-	};
+			lineNumberSizer.innerHTML = '';
+
+			info.lineHeights.forEach(function (height, lineNumber) {
+				wrapper.children[lineNumber].style.height = height + 'px';
+			});
+		});
+	}
 
 	/**
 	 * Returns style declarations for the element
@@ -63,7 +116,7 @@
 	};
 
 	window.addEventListener('resize', function () {
-		Array.prototype.forEach.call(document.querySelectorAll('pre.' + PLUGIN_NAME), _resizeElement);
+		resizeElements(Array.prototype.slice.call(document.querySelectorAll('pre.' + PLUGIN_NAME)));
 	});
 
 	Prism.hooks.add('complete', function (env) {
@@ -123,7 +176,7 @@
 
 		env.element.appendChild(lineNumbersWrapper);
 
-		_resizeElement(pre);
+		resizeElements([pre]);
 
 		Prism.hooks.run('line-numbers', env);
 	});
diff --git a/plugins/line-numbers/prism-line-numbers.min.js b/plugins/line-numbers/prism-line-numbers.min.js
index ca84bbe3e9..7632e31fc1 100644
--- a/plugins/line-numbers/prism-line-numbers.min.js
+++ b/plugins/line-numbers/prism-line-numbers.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var l="line-numbers",c=/\n(?!$)/g,m=function(e){var t=a(e)["white-space"];if("pre-wrap"===t||"pre-line"===t){var n=e.querySelector("code"),r=e.querySelector(".line-numbers-rows"),s=e.querySelector(".line-numbers-sizer"),i=n.textContent.split(c);s||((s=document.createElement("span")).className="line-numbers-sizer",n.appendChild(s)),s.style.display="block",i.forEach(function(e,t){s.textContent=e||"\n";var n=s.getBoundingClientRect().height;r.children[t].style.height=n+"px"}),s.textContent="",s.style.display="none"}},a=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null};window.addEventListener("resize",function(){Array.prototype.forEach.call(document.querySelectorAll("pre."+l),m)}),Prism.hooks.add("complete",function(e){if(e.code){var t=e.element,n=t.parentNode;if(n&&/pre/i.test(n.nodeName)&&!t.querySelector(".line-numbers-rows")){for(var r=!1,s=/(?:^|\s)line-numbers(?:\s|$)/,i=t;i;i=i.parentNode)if(s.test(i.className)){r=!0;break}if(r){t.className=t.className.replace(s," "),s.test(n.className)||(n.className+=" line-numbers");var l,a=e.code.match(c),o=a?a.length+1:1,u=new Array(o+1).join("");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=u,n.hasAttribute("data-start")&&(n.style.counterReset="linenumber "+(parseInt(n.getAttribute("data-start"),10)-1)),e.element.appendChild(l),m(n),Prism.hooks.run("line-numbers",e)}}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}),Prism.plugins.lineNumbers={getLine:function(e,t){if("PRE"===e.tagName&&e.classList.contains(l)){var n=e.querySelector(".line-numbers-rows"),r=parseInt(e.getAttribute("data-start"),10)||1,s=r+(n.children.length-1);t");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=c,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(l),d([t]),Prism.hooks.run("line-numbers",e)}}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}),Prism.plugins.lineNumbers={getLine:function(e,n){if("PRE"===e.tagName&&e.classList.contains(l)){var t=e.querySelector(".line-numbers-rows"),r=parseInt(e.getAttribute("data-start"),10)||1,i=r+(t.children.length-1);n
Date: Fri, 29 Nov 2019 18:47:45 +0100
Subject: [PATCH 2/4] Removed useless line break

---
 plugins/line-numbers/prism-line-numbers.js     | 1 -
 plugins/line-numbers/prism-line-numbers.min.js | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/plugins/line-numbers/prism-line-numbers.js b/plugins/line-numbers/prism-line-numbers.js
index b3b6bde751..8bdd3e1582 100644
--- a/plugins/line-numbers/prism-line-numbers.js
+++ b/plugins/line-numbers/prism-line-numbers.js
@@ -71,7 +71,6 @@
 					var e = lineNumberSizer.appendChild(document.createElement('span'));
 					e.style.display = 'block';
 					e.textContent = line;
-					lineNumberSizer.appendChild(document.createTextNode('\n'));
 				} else {
 					lineHeights[index] = oneLinerHeight;
 				}
diff --git a/plugins/line-numbers/prism-line-numbers.min.js b/plugins/line-numbers/prism-line-numbers.min.js
index 7632e31fc1..c2ee52f299 100644
--- a/plugins/line-numbers/prism-line-numbers.min.js
+++ b/plugins/line-numbers/prism-line-numbers.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var l="line-numbers",u=/\n(?!$)/g;window.addEventListener("resize",function(){d(Array.prototype.slice.call(document.querySelectorAll("pre."+l)))}),Prism.hooks.add("complete",function(e){if(e.code){var n=e.element,t=n.parentNode;if(t&&/pre/i.test(t.nodeName)&&!n.querySelector(".line-numbers-rows")){for(var r=!1,i=/(?:^|\s)line-numbers(?:\s|$)/,s=n;s;s=s.parentNode)if(i.test(s.className)){r=!0;break}if(r){n.className=n.className.replace(i," "),i.test(t.className)||(t.className+=" line-numbers");var l,a=e.code.match(u),o=a?a.length+1:1,c=new Array(o+1).join("");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=c,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(l),d([t]),Prism.hooks.run("line-numbers",e)}}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}),Prism.plugins.lineNumbers={getLine:function(e,n){if("PRE"===e.tagName&&e.classList.contains(l)){var t=e.querySelector(".line-numbers-rows"),r=parseInt(e.getAttribute("data-start"),10)||1,i=r+(t.children.length-1);n");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=u,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(l),d([t]),Prism.hooks.run("line-numbers",e)}}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}),Prism.plugins.lineNumbers={getLine:function(e,n){if("PRE"===e.tagName&&e.classList.contains(l)){var t=e.querySelector(".line-numbers-rows"),r=parseInt(e.getAttribute("data-start"),10)||1,i=r+(t.children.length-1);n
Date: Sat, 30 Nov 2019 22:40:55 +0100
Subject: [PATCH 3/4] Added optimization

---
 plugins/line-numbers/prism-line-numbers.js    | 83 ++++++++++++-------
 .../line-numbers/prism-line-numbers.min.js    |  2 +-
 2 files changed, 52 insertions(+), 33 deletions(-)

diff --git a/plugins/line-numbers/prism-line-numbers.js b/plugins/line-numbers/prism-line-numbers.js
index 8bdd3e1582..68d9a35506 100644
--- a/plugins/line-numbers/prism-line-numbers.js
+++ b/plugins/line-numbers/prism-line-numbers.js
@@ -16,6 +16,51 @@
 	 */
 	var NEW_LINE_EXP = /\n(?!$)/g;
 
+
+	/**
+	 * Global exports
+	 */
+	var config = Prism.plugins.lineNumbers = {
+		/**
+		 * Get node for provided line number
+		 * @param {Element} element pre element
+		 * @param {Number} number line number
+		 * @return {Element|undefined}
+		 */
+		getLine: function (element, number) {
+			if (element.tagName !== 'PRE' || !element.classList.contains(PLUGIN_NAME)) {
+				return;
+			}
+
+			var lineNumberRows = element.querySelector('.line-numbers-rows');
+			var lineNumberStart = parseInt(element.getAttribute('data-start'), 10) || 1;
+			var lineNumberEnd = lineNumberStart + (lineNumberRows.children.length - 1);
+
+			if (number < lineNumberStart) {
+				number = lineNumberStart;
+			}
+			if (number > lineNumberEnd) {
+				number = lineNumberEnd;
+			}
+
+			var lineIndex = number - lineNumberStart;
+
+			return lineNumberRows.children[lineIndex];
+		},
+
+		/**
+		 * Whether the plugin can assume that the units font sizes and margins are not depended on the size of
+		 * the current viewport.
+		 *
+		 * Setting this to `true` will allow the plugin to do certain optimizations for better performance.
+		 *
+		 * Set this to `false` if you use any of the following CSS units: `vh`, `vw`, `vmin`, `vmax`.
+		 *
+		 * @type {boolean}
+		 */
+		assumeViewportIndependence: false
+	};
+
 	/**
 	 * Resizes the given elements.
 	 *
@@ -114,7 +159,13 @@
 		return window.getComputedStyle ? getComputedStyle(element) : (element.currentStyle || null);
 	};
 
+	var lastWidth = undefined;
 	window.addEventListener('resize', function () {
+		if (config.assumeViewportIndependence && lastWidth === window.innerWidth) {
+			return;
+		}
+		lastWidth = window.innerWidth;
+
 		resizeElements(Array.prototype.slice.call(document.querySelectorAll('pre.' + PLUGIN_NAME)));
 	});
 
@@ -185,36 +236,4 @@
 		env.plugins.lineNumbers = true;
 	});
 
-	/**
-	 * Global exports
-	 */
-	Prism.plugins.lineNumbers = {
-		/**
-		 * Get node for provided line number
-		 * @param {Element} element pre element
-		 * @param {Number} number line number
-		 * @return {Element|undefined}
-		 */
-		getLine: function (element, number) {
-			if (element.tagName !== 'PRE' || !element.classList.contains(PLUGIN_NAME)) {
-				return;
-			}
-
-			var lineNumberRows = element.querySelector('.line-numbers-rows');
-			var lineNumberStart = parseInt(element.getAttribute('data-start'), 10) || 1;
-			var lineNumberEnd = lineNumberStart + (lineNumberRows.children.length - 1);
-
-			if (number < lineNumberStart) {
-				number = lineNumberStart;
-			}
-			if (number > lineNumberEnd) {
-				number = lineNumberEnd;
-			}
-
-			var lineIndex = number - lineNumberStart;
-
-			return lineNumberRows.children[lineIndex];
-		}
-	};
-
 }());
diff --git a/plugins/line-numbers/prism-line-numbers.min.js b/plugins/line-numbers/prism-line-numbers.min.js
index c2ee52f299..aae1409722 100644
--- a/plugins/line-numbers/prism-line-numbers.min.js
+++ b/plugins/line-numbers/prism-line-numbers.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var l="line-numbers",c=/\n(?!$)/g;window.addEventListener("resize",function(){d(Array.prototype.slice.call(document.querySelectorAll("pre."+l)))}),Prism.hooks.add("complete",function(e){if(e.code){var n=e.element,t=n.parentNode;if(t&&/pre/i.test(t.nodeName)&&!n.querySelector(".line-numbers-rows")){for(var r=!1,i=/(?:^|\s)line-numbers(?:\s|$)/,s=n;s;s=s.parentNode)if(i.test(s.className)){r=!0;break}if(r){n.className=n.className.replace(i," "),i.test(t.className)||(t.className+=" line-numbers");var l,a=e.code.match(c),o=a?a.length+1:1,u=new Array(o+1).join("");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=u,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(l),d([t]),Prism.hooks.run("line-numbers",e)}}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}),Prism.plugins.lineNumbers={getLine:function(e,n){if("PRE"===e.tagName&&e.classList.contains(l)){var t=e.querySelector(".line-numbers-rows"),r=parseInt(e.getAttribute("data-start"),10)||1,i=r+(t.children.length-1);n");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=u,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(l),d([t]),Prism.hooks.run("line-numbers",e)}}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0})}function d(e){if(0!=(e=e.filter(function(e){var n=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null}(e)["white-space"];return"pre-wrap"===n||"pre-line"===n})).length){var n=e.map(function(e){var n=e.querySelector("code"),t=e.querySelector(".line-numbers-sizer"),r=n.textContent.split(c);t||((t=document.createElement("span")).className="line-numbers-sizer",n.appendChild(t)),t.innerHTML="0",t.style.display="block";var i=t.getBoundingClientRect().height;return t.innerHTML="",{element:e,lines:r,lineHeights:[],oneLinerHeight:i,sizer:t}});n.forEach(function(e){var r=e.sizer,n=e.lines,i=e.lineHeights,s=e.oneLinerHeight;i[n.length-1]=void 0,n.forEach(function(e,n){if(e&&1
Date: Sun, 28 Jun 2020 02:48:40 +0200
Subject: [PATCH 4/4] Changed default value

---
 plugins/line-numbers/prism-line-numbers.js     | 2 +-
 plugins/line-numbers/prism-line-numbers.min.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/plugins/line-numbers/prism-line-numbers.js b/plugins/line-numbers/prism-line-numbers.js
index 471d8d4728..16012f604d 100644
--- a/plugins/line-numbers/prism-line-numbers.js
+++ b/plugins/line-numbers/prism-line-numbers.js
@@ -69,7 +69,7 @@
 		 *
 		 * @type {boolean}
 		 */
-		assumeViewportIndependence: false
+		assumeViewportIndependence: true
 	};
 
 	/**
diff --git a/plugins/line-numbers/prism-line-numbers.min.js b/plugins/line-numbers/prism-line-numbers.min.js
index fd99093a99..b0ee977c66 100644
--- a/plugins/line-numbers/prism-line-numbers.min.js
+++ b/plugins/line-numbers/prism-line-numbers.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var o="line-numbers",a=/\n(?!$)/g,e=Prism.plugins.lineNumbers={getLine:function(e,n){if("PRE"===e.tagName&&e.classList.contains(o)){var t=e.querySelector(".line-numbers-rows"),i=parseInt(e.getAttribute("data-start"),10)||1,r=i+(t.children.length-1);n");(i=document.createElement("span")).setAttribute("aria-hidden","true"),i.className="line-numbers-rows",i.innerHTML=l,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(i),u([t]),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0})}function u(e){if(0!=(e=e.filter(function(e){var n=t(e)["white-space"];return"pre-wrap"===n||"pre-line"===n})).length){var n=e.map(function(e){var n=e.querySelector("code"),t=e.querySelector(".line-numbers-rows");if(n&&t){var i=e.querySelector(".line-numbers-sizer"),r=n.textContent.split(a);i||((i=document.createElement("span")).className="line-numbers-sizer",n.appendChild(i)),i.innerHTML="0",i.style.display="block";var s=i.getBoundingClientRect().height;return i.innerHTML="",{element:e,lines:r,lineHeights:[],oneLinerHeight:s,sizer:i}}}).filter(Boolean);n.forEach(function(e){var i=e.sizer,n=e.lines,r=e.lineHeights,s=e.oneLinerHeight;r[n.length-1]=void 0,n.forEach(function(e,n){if(e&&1");(i=document.createElement("span")).setAttribute("aria-hidden","true"),i.className="line-numbers-rows",i.innerHTML=l,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(i),u([t]),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0})}function u(e){if(0!=(e=e.filter(function(e){var n=t(e)["white-space"];return"pre-wrap"===n||"pre-line"===n})).length){var n=e.map(function(e){var n=e.querySelector("code"),t=e.querySelector(".line-numbers-rows");if(n&&t){var i=e.querySelector(".line-numbers-sizer"),r=n.textContent.split(a);i||((i=document.createElement("span")).className="line-numbers-sizer",n.appendChild(i)),i.innerHTML="0",i.style.display="block";var s=i.getBoundingClientRect().height;return i.innerHTML="",{element:e,lines:r,lineHeights:[],oneLinerHeight:s,sizer:i}}}).filter(Boolean);n.forEach(function(e){var i=e.sizer,n=e.lines,r=e.lineHeights,s=e.oneLinerHeight;r[n.length-1]=void 0,n.forEach(function(e,n){if(e&&1