跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
中医百科
搜索
搜索
登录
个人工具
登录
深色模式
查看“MediaWiki:Gadget-TextSpacing.js”的源代码
系统消息
讨论
English
阅读
查看源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
查看源代码
查看历史
清除缓存
常规
链入页面
相关更改
特殊页面
页面信息
页面值
←
MediaWiki:Gadget-TextSpacing.js
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
此页面为本wiki上的软件提供界面文本,并受到保护以防止滥用。 如欲修改所有wiki的翻译,请访问
translatewiki.net
上的MediaWiki本地化项目。
您无权编辑此JavaScript页面,因为编辑此页面可能会影响所有访问者。
您必须确认您的电子邮件地址才能编辑页面。请通过
参数设置
设置并确认您的电子邮件地址。
您可以查看和复制此页面的源代码。
/** * SPDX-License-Identifier: BSD-3-Clause * _addText: '{{Gadget Header|license=BSD}}' * * @base {@link https://github.com/diskdance/gadget-text-spacing} * @source {@link https://git.qiuwen.net.cn/InterfaceAdmin/QiuwenGadgets/src/branch/master/src/TextSpacing} * @license BSD-3-Clause {@link https://github.com/diskdance/gadget-text-spacing/blob/main/LICENSE} */ /** * Copyright 2023 diskdance * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name of the author may not be used to * endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * +------------------------------------------------------------+ * | === WARNING: GLOBAL GADGET FILE === | * +------------------------------------------------------------+ * | All changes should be made in the repository, | * | otherwise they will be lost. | * +------------------------------------------------------------+ * | Changes to this page may affect many users. | * | Please discuss changes by opening an issue before editing. | * +------------------------------------------------------------+ */ /* <nowiki> */ (() => { "use strict"; var __getOwnPropNames = Object.getOwnPropertyNames; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; // node_modules/.pnpm/@mrhenry+core-web@1.2.3/node_modules/@mrhenry/core-web/modules/IntersectionObserver.js var require_IntersectionObserver = __commonJS({ "node_modules/.pnpm/@mrhenry+core-web@1.2.3/node_modules/@mrhenry/core-web/modules/IntersectionObserver.js"() { (function(undefined) { if (!("IntersectionObserver" in window && "IntersectionObserverEntry" in window && "intersectionRatio" in window.IntersectionObserverEntry.prototype)) { (function(window2, document2) { "use strict"; var supportedNatively = "IntersectionObserver" in window2 && "IntersectionObserverEntry" in window2 && "intersectionRatio" in window2.IntersectionObserverEntry.prototype; if (supportedNatively) { return; } var registry = []; function IntersectionObserverEntry(entry) { this.time = entry.time; this.target = entry.target; this.rootBounds = entry.rootBounds; this.boundingClientRect = entry.boundingClientRect; this.intersectionRect = entry.intersectionRect || getEmptyRect(); try { this.isIntersecting = !!entry.intersectionRect; } catch (err) { } var targetRect = this.boundingClientRect; var targetArea = targetRect.width * targetRect.height; var intersectionRect = this.intersectionRect; var intersectionArea = intersectionRect.width * intersectionRect.height; if (targetArea) { this.intersectionRatio = Number((intersectionArea / targetArea).toFixed(4)); } else { this.intersectionRatio = this.isIntersecting ? 1 : 0; } } IntersectionObserverEntry.prototype.intersectionRatio = 0; function IntersectionObserver2(callback, opt_options) { var options = opt_options || {}; if (typeof callback != "function") { throw new Error("callback must be a function"); } if (options.root && options.root.nodeType != 1) { throw new Error("root must be an Element"); } this._checkForIntersections = throttle( this._checkForIntersections.bind(this), this.THROTTLE_TIMEOUT ); this._callback = callback; this._observationTargets = []; this._queuedEntries = []; this._rootMarginValues = this._parseRootMargin(options.rootMargin); this.thresholds = this._initThresholds(options.threshold); this.root = options.root || null; this.rootMargin = this._rootMarginValues.map(function(margin) { return margin.value + margin.unit; }).join(" "); } IntersectionObserver2.prototype.THROTTLE_TIMEOUT = 100; IntersectionObserver2.prototype.POLL_INTERVAL = null; IntersectionObserver2.prototype.USE_MUTATION_OBSERVER = true; IntersectionObserver2.prototype.observe = function(target) { var isTargetAlreadyObserved = this._observationTargets.some(function(item) { return item.element == target; }); if (isTargetAlreadyObserved) { return; } if (!(target && target.nodeType == 1)) { throw new Error("target must be an Element"); } this._registerInstance(); this._observationTargets.push({ element: target, entry: null }); this._monitorIntersections(); this._checkForIntersections(); }; IntersectionObserver2.prototype.unobserve = function(target) { this._observationTargets = this._observationTargets.filter(function(item) { return item.element != target; }); if (!this._observationTargets.length) { this._unmonitorIntersections(); this._unregisterInstance(); } }; IntersectionObserver2.prototype.disconnect = function() { this._observationTargets = []; this._unmonitorIntersections(); this._unregisterInstance(); }; IntersectionObserver2.prototype.takeRecords = function() { var records = this._queuedEntries.slice(); this._queuedEntries = []; return records; }; IntersectionObserver2.prototype._initThresholds = function(opt_threshold) { var threshold = opt_threshold || [0]; if (!Array.isArray(threshold)) threshold = [threshold]; return threshold.sort().filter(function(t, i, a) { if (typeof t != "number" || isNaN(t) || t < 0 || t > 1) { throw new Error("threshold must be a number between 0 and 1 inclusively"); } return t !== a[i - 1]; }); }; IntersectionObserver2.prototype._parseRootMargin = function(opt_rootMargin) { var marginString = opt_rootMargin || "0px"; var margins = marginString.split(/\s+/).map(function(margin) { var parts = /^(-?\d*\.?\d+)(px|%)$/.exec(margin); if (!parts) { throw new Error("rootMargin must be specified in pixels or percent"); } return { value: parseFloat(parts[1]), unit: parts[2] }; }); margins[1] = margins[1] || margins[0]; margins[2] = margins[2] || margins[0]; margins[3] = margins[3] || margins[1]; return margins; }; IntersectionObserver2.prototype._monitorIntersections = function() { if (!this._monitoringIntersections) { this._monitoringIntersections = true; if (this.POLL_INTERVAL) { this._monitoringInterval = setInterval( this._checkForIntersections, this.POLL_INTERVAL ); } else { addEvent(window2, "resize", this._checkForIntersections, true); addEvent(document2, "scroll", this._checkForIntersections, true); if (this.USE_MUTATION_OBSERVER && "MutationObserver" in window2) { this._domObserver = new MutationObserver(this._checkForIntersections); this._domObserver.observe(document2, { attributes: true, childList: true, characterData: true, subtree: true }); } } } }; IntersectionObserver2.prototype._unmonitorIntersections = function() { if (this._monitoringIntersections) { this._monitoringIntersections = false; clearInterval(this._monitoringInterval); this._monitoringInterval = null; removeEvent(window2, "resize", this._checkForIntersections, true); removeEvent(document2, "scroll", this._checkForIntersections, true); if (this._domObserver) { this._domObserver.disconnect(); this._domObserver = null; } } }; IntersectionObserver2.prototype._checkForIntersections = function() { var rootIsInDom = this._rootIsInDom(); var rootRect = rootIsInDom ? this._getRootRect() : getEmptyRect(); this._observationTargets.forEach(function(item) { var target = item.element; var targetRect = getBoundingClientRect(target); var rootContainsTarget = this._rootContainsTarget(target); var oldEntry = item.entry; var intersectionRect = rootIsInDom && rootContainsTarget && this._computeTargetAndRootIntersection(target, rootRect); var newEntry = item.entry = new IntersectionObserverEntry({ time: now(), target, boundingClientRect: targetRect, rootBounds: rootRect, intersectionRect }); if (!oldEntry) { this._queuedEntries.push(newEntry); } else if (rootIsInDom && rootContainsTarget) { if (this._hasCrossedThreshold(oldEntry, newEntry)) { this._queuedEntries.push(newEntry); } } else { if (oldEntry && oldEntry.isIntersecting) { this._queuedEntries.push(newEntry); } } }, this); if (this._queuedEntries.length) { this._callback(this.takeRecords(), this); } }; IntersectionObserver2.prototype._computeTargetAndRootIntersection = function(target, rootRect) { if (window2.getComputedStyle(target).display == "none") return; var targetRect = getBoundingClientRect(target); var intersectionRect = targetRect; var parent = getParentNode(target); var atRoot = false; while (!atRoot) { var parentRect = null; var parentComputedStyle = parent.nodeType == 1 ? window2.getComputedStyle(parent) : {}; if (parentComputedStyle.display == "none") return; if (parent == this.root || parent == document2) { atRoot = true; parentRect = rootRect; } else { if (parent != document2.body && parent != document2.documentElement && parentComputedStyle.overflow != "visible") { parentRect = getBoundingClientRect(parent); } } if (parentRect) { intersectionRect = computeRectIntersection(parentRect, intersectionRect); if (!intersectionRect) break; } parent = getParentNode(parent); } return intersectionRect; }; IntersectionObserver2.prototype._getRootRect = function() { var rootRect; if (this.root) { rootRect = getBoundingClientRect(this.root); } else { var html = document2.documentElement; var body = document2.body; rootRect = { x: 0, y: 0, top: 0, left: 0, right: html.clientWidth || body.clientWidth, width: html.clientWidth || body.clientWidth, bottom: html.clientHeight || body.clientHeight, height: html.clientHeight || body.clientHeight }; } return this._expandRectByRootMargin(rootRect); }; IntersectionObserver2.prototype._expandRectByRootMargin = function(rect) { var margins = this._rootMarginValues.map(function(margin, i) { return margin.unit == "px" ? margin.value : margin.value * (i % 2 ? rect.width : rect.height) / 100; }); var newRect = { top: rect.top - margins[0], right: rect.right + margins[1], bottom: rect.bottom + margins[2], left: rect.left - margins[3] }; newRect.width = newRect.right - newRect.left; newRect.height = newRect.bottom - newRect.top; newRect.x = newRect.left; newRect.y = newRect.top; return newRect; }; IntersectionObserver2.prototype._hasCrossedThreshold = function(oldEntry, newEntry) { var oldRatio = oldEntry && oldEntry.isIntersecting ? oldEntry.intersectionRatio || 0 : -1; var newRatio = newEntry.isIntersecting ? newEntry.intersectionRatio || 0 : -1; if (oldRatio === newRatio) return; for (var i = 0; i < this.thresholds.length; i++) { var threshold = this.thresholds[i]; if (threshold == oldRatio || threshold == newRatio || threshold < oldRatio !== threshold < newRatio) { return true; } } }; IntersectionObserver2.prototype._rootIsInDom = function() { return !this.root || containsDeep(document2, this.root); }; IntersectionObserver2.prototype._rootContainsTarget = function(target) { return containsDeep(this.root || document2, target); }; IntersectionObserver2.prototype._registerInstance = function() { if (registry.indexOf(this) < 0) { registry.push(this); } }; IntersectionObserver2.prototype._unregisterInstance = function() { var index = registry.indexOf(this); if (index != -1) registry.splice(index, 1); }; function now() { return window2.performance && performance.now && performance.now(); } function throttle(fn, timeout) { var timer = null; return function() { if (!timer) { timer = setTimeout(function() { fn(); timer = null; }, timeout); } }; } function addEvent(node, event, fn, opt_useCapture) { if (typeof node.addEventListener == "function") { node.addEventListener(event, fn, opt_useCapture || false); } else if (typeof node.attachEvent == "function") { node.attachEvent("on" + event, fn); } } function removeEvent(node, event, fn, opt_useCapture) { if (typeof node.removeEventListener == "function") { node.removeEventListener(event, fn, opt_useCapture || false); } else if (typeof node.detatchEvent == "function") { node.detatchEvent("on" + event, fn); } } function computeRectIntersection(rect1, rect2) { var top = Math.max(rect1.top, rect2.top); var bottom = Math.min(rect1.bottom, rect2.bottom); var left = Math.max(rect1.left, rect2.left); var right = Math.min(rect1.right, rect2.right); var width = right - left; var height = bottom - top; return width >= 0 && height >= 0 && { x: left, y: top, top, bottom, left, right, width, height }; } function getBoundingClientRect(el) { var rect; try { rect = el.getBoundingClientRect(); } catch (err) { } if (!rect) return getEmptyRect(); if (!(rect.width && rect.height && rect.x && rect.y)) { rect = { x: rect.left, y: rect.top, top: rect.top, right: rect.right, bottom: rect.bottom, left: rect.left, width: rect.right - rect.left, height: rect.bottom - rect.top }; } return rect; } function getEmptyRect() { return { x: 0, y: 0, top: 0, bottom: 0, left: 0, right: 0, width: 0, height: 0 }; } function containsDeep(parent, child) { var node = child; while (node) { if (node == parent) return true; node = getParentNode(node); } return false; } function getParentNode(node) { var parent = node.parentNode; if (parent && parent.nodeType == 11 && parent.host) { return parent.host; } if (parent && parent.assignedSlot) { return parent.assignedSlot.parentNode; } return parent; } window2.IntersectionObserver = IntersectionObserver2; window2.IntersectionObserverEntry = IntersectionObserverEntry; })(window, document); } }).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {}); } }); // dist/TextSpacing/TextSpacing.js require_IntersectionObserver(); var _templateObject; var _templateObject2; var _templateObject3; function _taggedTemplateLiteral(e, t) { return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, { raw: { value: Object.freeze(t) } })); } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var n = 0, F = function() { }; return { s: F, n: function() { return n >= r.length ? { done: true } : { done: false, value: r[n++] }; }, e: function(r2) { throw r2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = true, u = false; return { s: function() { t = t.call(r); }, n: function() { var r2 = t.next(); return a = r2.done, r2; }, e: function(r2) { u = true, o = r2; }, f: function() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } //! src/TextSpacing/modules/util.ts var import_ext_gadget = require("ext.gadget.Util"); var isInlineHTMLElement = (node) => { return node instanceof HTMLElement && window.getComputedStyle(node).display.includes("inline"); }; var isTextNode = (node) => { return node.nodeType === Node.TEXT_NODE; }; var isVisible = (element) => { const style = window.getComputedStyle(element); return style.display !== "none" && !["hidden", "collapse"].includes(style.visibility) && Number.parseFloat(style.opacity) > 0; }; var getNodeText = (node) => { return node instanceof HTMLElement ? node.innerText : node.data; }; var splitAtIndexes = (str, indexes) => { const result = []; const normalizedIndexes = [ // Remove duplications and sort in ascending order ...(0, import_ext_gadget.uniqueArray)( // Replace `new Set()` to avoid polyfilling core-js indexes.sort((a, b) => { return a - b; }).filter((i) => { return i >= 0 && i <= str.length; }) ), str.length ]; for (let i = 0; i < normalizedIndexes.length; i++) { const slice = str.slice(normalizedIndexes[i - 1], normalizedIndexes[i]); result[result.length] = slice; } return result; }; //! src/TextSpacing/modules/queue.ts var pendingActions = /* @__PURE__ */ new WeakMap(); var onIntersection = (entries) => { var _iterator = _createForOfIteratorHelper(entries), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done; ) { const entry = _step.value; if (!entry.isIntersecting) { continue; } const element = entry.target; observer.unobserve(element); const callbacks = pendingActions.get(element); if (!callbacks) { continue; } while (true) { const callback = callbacks.shift(); if (!callback) { break; } callback(element); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } }; var observer = new IntersectionObserver(onIntersection); var queueDomMutation = (element, callback) => { if (!pendingActions.has(element)) { pendingActions.set(element, []); } if (pendingActions.get(element) !== void 0) { pendingActions.get(element)[pendingActions.get(element).length] = callback; } observer.observe(element); }; //! src/TextSpacing/modules/spacing.ts var REGEX_RANGE_CHINESE = String.raw(_templateObject || (_templateObject = _taggedTemplateLiteral(["(?:[⺀-⺙⺛-⻳⼀-⿕々〇〡-〩〸-〻㐀-䶿一-鿿豈-舘並-龎]|\uD81B[\uDFE2\uDFE3\uDFF0\uDFF1]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])"], ["(?:[\\u2E80-\\u2E99\\u2E9B-\\u2EF3\\u2F00-\\u2FD5\\u3005\\u3007\\u3021-\\u3029\\u3038-\\u303B\\u3400-\\u4DBF\\u4E00-\\u9FFF\\uF900-\\uFA6D\\uFA70-\\uFAD9]|\\uD81B[\\uDFE2\\uDFE3\\uDFF0\\uDFF1]|[\\uD840-\\uD868\\uD86A-\\uD86C\\uD86F-\\uD872\\uD874-\\uD879\\uD880-\\uD883][\\uDC00-\\uDFFF]|\\uD869[\\uDC00-\\uDEDF\\uDF00-\\uDFFF]|\\uD86D[\\uDC00-\\uDF38\\uDF40-\\uDFFF]|\\uD86E[\\uDC00-\\uDC1D\\uDC20-\\uDFFF]|\\uD873[\\uDC00-\\uDEA1\\uDEB0-\\uDFFF]|\\uD87A[\\uDC00-\\uDFE0]|\\uD87E[\\uDC00-\\uDE1D]|\\uD884[\\uDC00-\\uDF4A])"]))); var REGEX_RANGE_OTHER_LEFT = String.raw(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["[A-Za-z0-9@~%+=|±)}#$¥€£₤]"], ["[A-Za-z0-9@~%+=|±\\)}#$¥€£₤]"]))); var REGEX_RANGE_OTHER_RIGHT = String.raw(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["[A-Za-z0-9@~%+=|±({#$¥€£₤]"], ["[A-Za-z0-9@~%+=|±\\({#$¥€£₤]"]))); var REGEX_STR_INTER_SCRIPT = "(?:(".concat(REGEX_RANGE_CHINESE, ")(?=").concat(REGEX_RANGE_OTHER_RIGHT, ")|(").concat(REGEX_RANGE_OTHER_LEFT, ")(?=").concat(REGEX_RANGE_CHINESE, "))"); var SPACE = " "; var WRAPPER_CLASS = "gadget-text_spacing"; var SELECTOR_ALLOWED = ["a", "abbr", "article", "aside", "b", "bdi", "big", "blockquote", "button", "caption", "center", "cite", "data", "dd", "del", "details", "dfn", "div", "dt", "em", "figcaption", "footer", "h1", "h2", "h3", "h4", "h5", "header", "i", "ins", "label", "legend", "li", "main", "mark", "option", "p", "q", "ruby", "s", "section", "small", "span", "strike", "strong", "sub", "summary", "sup", "td", "th", "time", "u"]; var SELECTOR_BLOCKED = [ "code", "kbd", "pre", "rp", "rt", "samp", "textarea", "var", // Elements with this class are excluded ".gadget-nospace", // Editable elements '[contenteditable="true"]', // ACE editor content ".ace_editor", // Visual Editor (and 2017 Wikitext Editor) content & diff ".ve-ui-surface", ".ve-init-mw-diffPage-diff", // Diff ".diff-context", ".diff-addedline", ".diff-deletedline", // Diff (inline mode) ".mw-diff-inline-added", ".mw-diff-inline-deleted", ".mw-diff-inline-moved", ".mw-diff-inline-changed", ".mw-diff-inline-context" ]; var SELECTOR = SELECTOR_ALLOWED.map((allowed) => { return "".concat(allowed, ":not(").concat(SELECTOR_BLOCKED.flatMap((blocked) => { return blocked[0].match(/[a-z]/i) ? "".concat(blocked, " *") : [blocked, "".concat(blocked, " *")]; }).join(","), ")"); }).join(","); var getLeafElements = (parent) => { const candidates = parent.querySelectorAll(SELECTOR); const result = []; if (parent.matches(SELECTOR)) { result[result.length] = parent; } var _iterator2 = _createForOfIteratorHelper(candidates), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done; ) { const candidate = _step2.value; var _iterator3 = _createForOfIteratorHelper(candidate.childNodes), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done; ) { const childNode = _step3.value; if (isTextNode(childNode)) { result[result.length] = candidate; break; } } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } return result; }; var getNextVisibleSibling = (node) => { let currentNode = node; while (true) { const candidate = currentNode.nextSibling; if (!candidate) { const parent = currentNode.parentElement; if (!parent) { return null; } currentNode = parent; continue; } if (!(candidate instanceof HTMLElement || candidate instanceof Text)) { currentNode = candidate; continue; } if (candidate instanceof HTMLElement) { if (!isVisible(candidate)) { currentNode = candidate; continue; } if (!isInlineHTMLElement(candidate)) { return null; } } if (candidate instanceof Text && !candidate.data.trim()) { currentNode = candidate; continue; } return candidate; } }; var createSpacingWrapper = (str) => { const span = document.createElement("span"); span.className = WRAPPER_CLASS; span.textContent = str.slice(-1); return [str.slice(0, -1), span]; }; var adjustSpacing = (element) => { const childNodes = [...element.childNodes]; const textSpacingPosMap = /* @__PURE__ */ new Map(); for (var _i = 0, _childNodes = childNodes; _i < _childNodes.length; _i++) { const child = _childNodes[_i]; if (!(child instanceof Text)) { continue; } const nextSibling = getNextVisibleSibling(child); let testString = getNodeText(child); if (nextSibling) { var _getNodeText$; testString += (_getNodeText$ = getNodeText(nextSibling)[0]) !== null && _getNodeText$ !== void 0 ? _getNodeText$ : ""; } const indexes = []; const regexTextNodeData = new RegExp(REGEX_STR_INTER_SCRIPT, "g"); while (true) { const match = regexTextNodeData.exec(testString); if (!match) { break; } indexes[indexes.length] = match.index + 1; } if (!indexes.length) { continue; } textSpacingPosMap.set(child, indexes); } queueDomMutation(element, () => { var _iterator4 = _createForOfIteratorHelper(textSpacingPosMap), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done; ) { const [node, indexes] = _step4.value; const text = node.data; const fragments = splitAtIndexes(text, indexes); const replacement = fragments.slice(0, -1).flatMap((fragment) => { return createSpacingWrapper(fragment); }); replacement[replacement.length] = fragments.at(-1); requestAnimationFrame(() => { node.replaceWith(...replacement); }); } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } }); }; var addSpaceToString = (str) => { const regex = new RegExp(REGEX_STR_INTER_SCRIPT, "g"); return str.replace(regex, "$1$2".concat(SPACE)); }; //! src/TextSpacing/TextSpacing.ts var run = (element) => { const leaves = getLeafElements(element); var _iterator5 = _createForOfIteratorHelper(leaves), _step5; try { for (_iterator5.s(); !(_step5 = _iterator5.n()).done; ) { const leaf = _step5.value; adjustSpacing(leaf); } } catch (err) { _iterator5.e(err); } finally { _iterator5.f(); } }; var mutationObserver = new MutationObserver((records) => { var _iterator6 = _createForOfIteratorHelper(records), _step6; try { for (_iterator6.s(); !(_step6 = _iterator6.n()).done; ) { const record = _step6.value; if (record.type !== "childList") { continue; } const addedNodes = [...record.addedNodes]; if (addedNodes.some((node) => { return node instanceof HTMLElement && node.classList.contains(WRAPPER_CLASS); })) { continue; } for (var _i2 = 0, _addedNodes = addedNodes; _i2 < _addedNodes.length; _i2++) { const node = _addedNodes[_i2]; if (node instanceof HTMLElement) { run(node); } else if (node instanceof Text) { const { parentElement } = node; if (parentElement) { run(parentElement); } } } } } catch (err) { _iterator6.e(err); } finally { _iterator6.f(); } }); var main = () => { document.title = addSpaceToString(document.title); mutationObserver.observe(document.body, { subtree: true, childList: true }); run(document.body); }; $(main); })();
该页面使用的模板:
Template:Gadget Header
(
查看源代码
)
返回
MediaWiki:Gadget-TextSpacing.js
。
开关有限宽度模式