From f0d0ae5755e84cc938162ceef4beeb0d3763aead Mon Sep 17 00:00:00 2001 From: amy21206 Date: Tue, 27 Dec 2022 11:39:20 -0500 Subject: [PATCH 1/2] :arrow_up: hparsons: Update to a more lightweight version of custom element --- runestone/hparsons/js/horizontal-parsons.js | 20587 ------------------ runestone/hparsons/js/hparsons-sql.js | 10 +- runestone/hparsons/js/micro-parsons.js | 8 + 3 files changed, 13 insertions(+), 20592 deletions(-) delete mode 100644 runestone/hparsons/js/horizontal-parsons.js create mode 100644 runestone/hparsons/js/micro-parsons.js diff --git a/runestone/hparsons/js/horizontal-parsons.js b/runestone/hparsons/js/horizontal-parsons.js deleted file mode 100644 index 5891d6c07..000000000 --- a/runestone/hparsons/js/horizontal-parsons.js +++ /dev/null @@ -1,20587 +0,0 @@ -/**! - * Sortable 1.14.0 - * @author RubaXa - * @author owenm - * @license MIT - */ -function ownKeys(object, enumerableOnly) { - var keys = Object.keys(object); - - if (Object.getOwnPropertySymbols) { - var symbols = Object.getOwnPropertySymbols(object); - - if (enumerableOnly) { - symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - }); - } - - keys.push.apply(keys, symbols); - } - - return keys; -} - -function _objectSpread2(target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i] != null ? arguments[i] : {}; - - if (i % 2) { - ownKeys(Object(source), true).forEach(function (key) { - _defineProperty(target, key, source[key]); - }); - } else if (Object.getOwnPropertyDescriptors) { - Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); - } else { - ownKeys(Object(source)).forEach(function (key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); - }); - } - } - - return target; -} - -function _typeof(obj) { - "@babel/helpers - typeof"; - - if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { - _typeof = function (obj) { - return typeof obj; - }; - } else { - _typeof = function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - } - - return _typeof(obj); -} - -function _defineProperty(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - - return obj; -} - -function _extends() { - _extends = Object.assign || function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; - - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - - return target; - }; - - return _extends.apply(this, arguments); -} - -function _objectWithoutPropertiesLoose(source, excluded) { - if (source == null) return {}; - var target = {}; - var sourceKeys = Object.keys(source); - var key, i; - - for (i = 0; i < sourceKeys.length; i++) { - key = sourceKeys[i]; - if (excluded.indexOf(key) >= 0) continue; - target[key] = source[key]; - } - - return target; -} - -function _objectWithoutProperties(source, excluded) { - if (source == null) return {}; - - var target = _objectWithoutPropertiesLoose(source, excluded); - - var key, i; - - if (Object.getOwnPropertySymbols) { - var sourceSymbolKeys = Object.getOwnPropertySymbols(source); - - for (i = 0; i < sourceSymbolKeys.length; i++) { - key = sourceSymbolKeys[i]; - if (excluded.indexOf(key) >= 0) continue; - if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; - target[key] = source[key]; - } - } - - return target; -} - -var version$1 = "1.14.0"; - -function userAgent(pattern) { - if (typeof window !== 'undefined' && window.navigator) { - return !! /*@__PURE__*/navigator.userAgent.match(pattern); - } -} - -var IE11OrLess = userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i); -var Edge = userAgent(/Edge/i); -var FireFox = userAgent(/firefox/i); -var Safari = userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i); -var IOS = userAgent(/iP(ad|od|hone)/i); -var ChromeForAndroid = userAgent(/chrome/i) && userAgent(/android/i); - -var captureMode = { - capture: false, - passive: false -}; - -function on(el, event, fn) { - el.addEventListener(event, fn, !IE11OrLess && captureMode); -} - -function off(el, event, fn) { - el.removeEventListener(event, fn, !IE11OrLess && captureMode); -} - -function matches( -/**HTMLElement*/ -el, -/**String*/ -selector) { - if (!selector) return; - selector[0] === '>' && (selector = selector.substring(1)); - - if (el) { - try { - if (el.matches) { - return el.matches(selector); - } else if (el.msMatchesSelector) { - return el.msMatchesSelector(selector); - } else if (el.webkitMatchesSelector) { - return el.webkitMatchesSelector(selector); - } - } catch (_) { - return false; - } - } - - return false; -} - -function getParentOrHost(el) { - return el.host && el !== document && el.host.nodeType ? el.host : el.parentNode; -} - -function closest( -/**HTMLElement*/ -el, -/**String*/ -selector, -/**HTMLElement*/ -ctx, includeCTX) { - if (el) { - ctx = ctx || document; - - do { - if (selector != null && (selector[0] === '>' ? el.parentNode === ctx && matches(el, selector) : matches(el, selector)) || includeCTX && el === ctx) { - return el; - } - - if (el === ctx) break; - /* jshint boss:true */ - } while (el = getParentOrHost(el)); - } - - return null; -} - -var R_SPACE = /\s+/g; - -function toggleClass(el, name, state) { - if (el && name) { - if (el.classList) { - el.classList[state ? 'add' : 'remove'](name); - } else { - var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' '); - el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' '); - } - } -} - -function css(el, prop, val) { - var style = el && el.style; - - if (style) { - if (val === void 0) { - if (document.defaultView && document.defaultView.getComputedStyle) { - val = document.defaultView.getComputedStyle(el, ''); - } else if (el.currentStyle) { - val = el.currentStyle; - } - - return prop === void 0 ? val : val[prop]; - } else { - if (!(prop in style) && prop.indexOf('webkit') === -1) { - prop = '-webkit-' + prop; - } - - style[prop] = val + (typeof val === 'string' ? '' : 'px'); - } - } -} - -function matrix(el, selfOnly) { - var appliedTransforms = ''; - - if (typeof el === 'string') { - appliedTransforms = el; - } else { - do { - var transform = css(el, 'transform'); - - if (transform && transform !== 'none') { - appliedTransforms = transform + ' ' + appliedTransforms; - } - /* jshint boss:true */ - - } while (!selfOnly && (el = el.parentNode)); - } - - var matrixFn = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix; - /*jshint -W056 */ - - return matrixFn && new matrixFn(appliedTransforms); -} - -function find(ctx, tagName, iterator) { - if (ctx) { - var list = ctx.getElementsByTagName(tagName), - i = 0, - n = list.length; - - if (iterator) { - for (; i < n; i++) { - iterator(list[i], i); - } - } - - return list; - } - - return []; -} - -function getWindowScrollingElement() { - var scrollingElement = document.scrollingElement; - - if (scrollingElement) { - return scrollingElement; - } else { - return document.documentElement; - } -} -/** - * Returns the "bounding client rect" of given element - * @param {HTMLElement} el The element whose boundingClientRect is wanted - * @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container - * @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr - * @param {[Boolean]} undoScale Whether the container's scale() should be undone - * @param {[HTMLElement]} container The parent the element will be placed in - * @return {Object} The boundingClientRect of el, with specified adjustments - */ - - -function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) { - if (!el.getBoundingClientRect && el !== window) return; - var elRect, top, left, bottom, right, height, width; - - if (el !== window && el.parentNode && el !== getWindowScrollingElement()) { - elRect = el.getBoundingClientRect(); - top = elRect.top; - left = elRect.left; - bottom = elRect.bottom; - right = elRect.right; - height = elRect.height; - width = elRect.width; - } else { - top = 0; - left = 0; - bottom = window.innerHeight; - right = window.innerWidth; - height = window.innerHeight; - width = window.innerWidth; - } - - if ((relativeToContainingBlock || relativeToNonStaticParent) && el !== window) { - // Adjust for translate() - container = container || el.parentNode; // solves #1123 (see: https://stackoverflow.com/a/37953806/6088312) - // Not needed on <= IE11 - - if (!IE11OrLess) { - do { - if (container && container.getBoundingClientRect && (css(container, 'transform') !== 'none' || relativeToNonStaticParent && css(container, 'position') !== 'static')) { - var containerRect = container.getBoundingClientRect(); // Set relative to edges of padding box of container - - top -= containerRect.top + parseInt(css(container, 'border-top-width')); - left -= containerRect.left + parseInt(css(container, 'border-left-width')); - bottom = top + elRect.height; - right = left + elRect.width; - break; - } - /* jshint boss:true */ - - } while (container = container.parentNode); - } - } - - if (undoScale && el !== window) { - // Adjust for scale() - var elMatrix = matrix(container || el), - scaleX = elMatrix && elMatrix.a, - scaleY = elMatrix && elMatrix.d; - - if (elMatrix) { - top /= scaleY; - left /= scaleX; - width /= scaleX; - height /= scaleY; - bottom = top + height; - right = left + width; - } - } - - return { - top: top, - left: left, - bottom: bottom, - right: right, - width: width, - height: height - }; -} -/** - * Checks if a side of an element is scrolled past a side of its parents - * @param {HTMLElement} el The element who's side being scrolled out of view is in question - * @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom') - * @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom') - * @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element - */ - - -function isScrolledPast(el, elSide, parentSide) { - var parent = getParentAutoScrollElement(el, true), - elSideVal = getRect(el)[elSide]; - /* jshint boss:true */ - - while (parent) { - var parentSideVal = getRect(parent)[parentSide], - visible = void 0; - - if (parentSide === 'top' || parentSide === 'left') { - visible = elSideVal >= parentSideVal; - } else { - visible = elSideVal <= parentSideVal; - } - - if (!visible) return parent; - if (parent === getWindowScrollingElement()) break; - parent = getParentAutoScrollElement(parent, false); - } - - return false; -} -/** - * Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible) - * and non-draggable elements - * @param {HTMLElement} el The parent element - * @param {Number} childNum The index of the child - * @param {Object} options Parent Sortable's options - * @return {HTMLElement} The child at index childNum, or null if not found - */ - - -function getChild(el, childNum, options, includeDragEl) { - var currentChild = 0, - i = 0, - children = el.children; - - while (i < children.length) { - if (children[i].style.display !== 'none' && children[i] !== Sortable.ghost && (includeDragEl || children[i] !== Sortable.dragged) && closest(children[i], options.draggable, el, false)) { - if (currentChild === childNum) { - return children[i]; - } - - currentChild++; - } - - i++; - } - - return null; -} -/** - * Gets the last child in the el, ignoring ghostEl or invisible elements (clones) - * @param {HTMLElement} el Parent element - * @param {selector} selector Any other elements that should be ignored - * @return {HTMLElement} The last child, ignoring ghostEl - */ - - -function lastChild(el, selector) { - var last = el.lastElementChild; - - while (last && (last === Sortable.ghost || css(last, 'display') === 'none' || selector && !matches(last, selector))) { - last = last.previousElementSibling; - } - - return last || null; -} -/** - * Returns the index of an element within its parent for a selected set of - * elements - * @param {HTMLElement} el - * @param {selector} selector - * @return {number} - */ - - -function index(el, selector) { - var index = 0; - - if (!el || !el.parentNode) { - return -1; - } - /* jshint boss:true */ - - - while (el = el.previousElementSibling) { - if (el.nodeName.toUpperCase() !== 'TEMPLATE' && el !== Sortable.clone && (!selector || matches(el, selector))) { - index++; - } - } - - return index; -} -/** - * Returns the scroll offset of the given element, added with all the scroll offsets of parent elements. - * The value is returned in real pixels. - * @param {HTMLElement} el - * @return {Array} Offsets in the format of [left, top] - */ - - -function getRelativeScrollOffset(el) { - var offsetLeft = 0, - offsetTop = 0, - winScroller = getWindowScrollingElement(); - - if (el) { - do { - var elMatrix = matrix(el), - scaleX = elMatrix.a, - scaleY = elMatrix.d; - offsetLeft += el.scrollLeft * scaleX; - offsetTop += el.scrollTop * scaleY; - } while (el !== winScroller && (el = el.parentNode)); - } - - return [offsetLeft, offsetTop]; -} -/** - * Returns the index of the object within the given array - * @param {Array} arr Array that may or may not hold the object - * @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find - * @return {Number} The index of the object in the array, or -1 - */ - - -function indexOfObject(arr, obj) { - for (var i in arr) { - if (!arr.hasOwnProperty(i)) continue; - - for (var key in obj) { - if (obj.hasOwnProperty(key) && obj[key] === arr[i][key]) return Number(i); - } - } - - return -1; -} - -function getParentAutoScrollElement(el, includeSelf) { - // skip to window - if (!el || !el.getBoundingClientRect) return getWindowScrollingElement(); - var elem = el; - var gotSelf = false; - - do { - // we don't need to get elem css if it isn't even overflowing in the first place (performance) - if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) { - var elemCSS = css(elem); - - if (elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') || elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')) { - if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement(); - if (gotSelf || includeSelf) return elem; - gotSelf = true; - } - } - /* jshint boss:true */ - - } while (elem = elem.parentNode); - - return getWindowScrollingElement(); -} - -function extend(dst, src) { - if (dst && src) { - for (var key in src) { - if (src.hasOwnProperty(key)) { - dst[key] = src[key]; - } - } - } - - return dst; -} - -function isRectEqual(rect1, rect2) { - return Math.round(rect1.top) === Math.round(rect2.top) && Math.round(rect1.left) === Math.round(rect2.left) && Math.round(rect1.height) === Math.round(rect2.height) && Math.round(rect1.width) === Math.round(rect2.width); -} - -var _throttleTimeout; - -function throttle(callback, ms) { - return function () { - if (!_throttleTimeout) { - var args = arguments, - _this = this; - - if (args.length === 1) { - callback.call(_this, args[0]); - } else { - callback.apply(_this, args); - } - - _throttleTimeout = setTimeout(function () { - _throttleTimeout = void 0; - }, ms); - } - }; -} - -function cancelThrottle() { - clearTimeout(_throttleTimeout); - _throttleTimeout = void 0; -} - -function scrollBy(el, x, y) { - el.scrollLeft += x; - el.scrollTop += y; -} - -function clone(el) { - var Polymer = window.Polymer; - var $ = window.jQuery || window.Zepto; - - if (Polymer && Polymer.dom) { - return Polymer.dom(el).cloneNode(true); - } else if ($) { - return $(el).clone(true)[0]; - } else { - return el.cloneNode(true); - } -} - -var expando = 'Sortable' + new Date().getTime(); - -function AnimationStateManager() { - var animationStates = [], - animationCallbackId; - return { - captureAnimationState: function captureAnimationState() { - animationStates = []; - if (!this.options.animation) return; - var children = [].slice.call(this.el.children); - children.forEach(function (child) { - if (css(child, 'display') === 'none' || child === Sortable.ghost) return; - animationStates.push({ - target: child, - rect: getRect(child) - }); - - var fromRect = _objectSpread2({}, animationStates[animationStates.length - 1].rect); // If animating: compensate for current animation - - - if (child.thisAnimationDuration) { - var childMatrix = matrix(child, true); - - if (childMatrix) { - fromRect.top -= childMatrix.f; - fromRect.left -= childMatrix.e; - } - } - - child.fromRect = fromRect; - }); - }, - addAnimationState: function addAnimationState(state) { - animationStates.push(state); - }, - removeAnimationState: function removeAnimationState(target) { - animationStates.splice(indexOfObject(animationStates, { - target: target - }), 1); - }, - animateAll: function animateAll(callback) { - var _this = this; - - if (!this.options.animation) { - clearTimeout(animationCallbackId); - if (typeof callback === 'function') callback(); - return; - } - - var animating = false, - animationTime = 0; - animationStates.forEach(function (state) { - var time = 0, - target = state.target, - fromRect = target.fromRect, - toRect = getRect(target), - prevFromRect = target.prevFromRect, - prevToRect = target.prevToRect, - animatingRect = state.rect, - targetMatrix = matrix(target, true); - - if (targetMatrix) { - // Compensate for current animation - toRect.top -= targetMatrix.f; - toRect.left -= targetMatrix.e; - } - - target.toRect = toRect; - - if (target.thisAnimationDuration) { - // Could also check if animatingRect is between fromRect and toRect - if (isRectEqual(prevFromRect, toRect) && !isRectEqual(fromRect, toRect) && // Make sure animatingRect is on line between toRect & fromRect - (animatingRect.top - toRect.top) / (animatingRect.left - toRect.left) === (fromRect.top - toRect.top) / (fromRect.left - toRect.left)) { - // If returning to same place as started from animation and on same axis - time = calculateRealTime(animatingRect, prevFromRect, prevToRect, _this.options); - } - } // if fromRect != toRect: animate - - - if (!isRectEqual(toRect, fromRect)) { - target.prevFromRect = fromRect; - target.prevToRect = toRect; - - if (!time) { - time = _this.options.animation; - } - - _this.animate(target, animatingRect, toRect, time); - } - - if (time) { - animating = true; - animationTime = Math.max(animationTime, time); - clearTimeout(target.animationResetTimer); - target.animationResetTimer = setTimeout(function () { - target.animationTime = 0; - target.prevFromRect = null; - target.fromRect = null; - target.prevToRect = null; - target.thisAnimationDuration = null; - }, time); - target.thisAnimationDuration = time; - } - }); - clearTimeout(animationCallbackId); - - if (!animating) { - if (typeof callback === 'function') callback(); - } else { - animationCallbackId = setTimeout(function () { - if (typeof callback === 'function') callback(); - }, animationTime); - } - - animationStates = []; - }, - animate: function animate(target, currentRect, toRect, duration) { - if (duration) { - css(target, 'transition', ''); - css(target, 'transform', ''); - var elMatrix = matrix(this.el), - scaleX = elMatrix && elMatrix.a, - scaleY = elMatrix && elMatrix.d, - translateX = (currentRect.left - toRect.left) / (scaleX || 1), - translateY = (currentRect.top - toRect.top) / (scaleY || 1); - target.animatingX = !!translateX; - target.animatingY = !!translateY; - css(target, 'transform', 'translate3d(' + translateX + 'px,' + translateY + 'px,0)'); - this.forRepaintDummy = repaint(target); // repaint - - css(target, 'transition', 'transform ' + duration + 'ms' + (this.options.easing ? ' ' + this.options.easing : '')); - css(target, 'transform', 'translate3d(0,0,0)'); - typeof target.animated === 'number' && clearTimeout(target.animated); - target.animated = setTimeout(function () { - css(target, 'transition', ''); - css(target, 'transform', ''); - target.animated = false; - target.animatingX = false; - target.animatingY = false; - }, duration); - } - } - }; -} - -function repaint(target) { - return target.offsetWidth; -} - -function calculateRealTime(animatingRect, fromRect, toRect, options) { - return Math.sqrt(Math.pow(fromRect.top - animatingRect.top, 2) + Math.pow(fromRect.left - animatingRect.left, 2)) / Math.sqrt(Math.pow(fromRect.top - toRect.top, 2) + Math.pow(fromRect.left - toRect.left, 2)) * options.animation; -} - -var plugins = []; -var defaults = { - initializeByDefault: true -}; -var PluginManager = { - mount: function mount(plugin) { - // Set default static properties - for (var option in defaults) { - if (defaults.hasOwnProperty(option) && !(option in plugin)) { - plugin[option] = defaults[option]; - } - } - - plugins.forEach(function (p) { - if (p.pluginName === plugin.pluginName) { - throw "Sortable: Cannot mount plugin ".concat(plugin.pluginName, " more than once"); - } - }); - plugins.push(plugin); - }, - pluginEvent: function pluginEvent(eventName, sortable, evt) { - var _this = this; - - this.eventCanceled = false; - - evt.cancel = function () { - _this.eventCanceled = true; - }; - - var eventNameGlobal = eventName + 'Global'; - plugins.forEach(function (plugin) { - if (!sortable[plugin.pluginName]) return; // Fire global events if it exists in this sortable - - if (sortable[plugin.pluginName][eventNameGlobal]) { - sortable[plugin.pluginName][eventNameGlobal](_objectSpread2({ - sortable: sortable - }, evt)); - } // Only fire plugin event if plugin is enabled in this sortable, - // and plugin has event defined - - - if (sortable.options[plugin.pluginName] && sortable[plugin.pluginName][eventName]) { - sortable[plugin.pluginName][eventName](_objectSpread2({ - sortable: sortable - }, evt)); - } - }); - }, - initializePlugins: function initializePlugins(sortable, el, defaults, options) { - plugins.forEach(function (plugin) { - var pluginName = plugin.pluginName; - if (!sortable.options[pluginName] && !plugin.initializeByDefault) return; - var initialized = new plugin(sortable, el, sortable.options); - initialized.sortable = sortable; - initialized.options = sortable.options; - sortable[pluginName] = initialized; // Add default options from plugin - - _extends(defaults, initialized.defaults); - }); - - for (var option in sortable.options) { - if (!sortable.options.hasOwnProperty(option)) continue; - var modified = this.modifyOption(sortable, option, sortable.options[option]); - - if (typeof modified !== 'undefined') { - sortable.options[option] = modified; - } - } - }, - getEventProperties: function getEventProperties(name, sortable) { - var eventProperties = {}; - plugins.forEach(function (plugin) { - if (typeof plugin.eventProperties !== 'function') return; - - _extends(eventProperties, plugin.eventProperties.call(sortable[plugin.pluginName], name)); - }); - return eventProperties; - }, - modifyOption: function modifyOption(sortable, name, value) { - var modifiedValue; - plugins.forEach(function (plugin) { - // Plugin must exist on the Sortable - if (!sortable[plugin.pluginName]) return; // If static option listener exists for this option, call in the context of the Sortable's instance of this plugin - - if (plugin.optionListeners && typeof plugin.optionListeners[name] === 'function') { - modifiedValue = plugin.optionListeners[name].call(sortable[plugin.pluginName], value); - } - }); - return modifiedValue; - } -}; - -function dispatchEvent(_ref) { - var sortable = _ref.sortable, - rootEl = _ref.rootEl, - name = _ref.name, - targetEl = _ref.targetEl, - cloneEl = _ref.cloneEl, - toEl = _ref.toEl, - fromEl = _ref.fromEl, - oldIndex = _ref.oldIndex, - newIndex = _ref.newIndex, - oldDraggableIndex = _ref.oldDraggableIndex, - newDraggableIndex = _ref.newDraggableIndex, - originalEvent = _ref.originalEvent, - putSortable = _ref.putSortable, - extraEventProperties = _ref.extraEventProperties; - sortable = sortable || rootEl && rootEl[expando]; - if (!sortable) return; - var evt, - options = sortable.options, - onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); // Support for new CustomEvent feature - - if (window.CustomEvent && !IE11OrLess && !Edge) { - evt = new CustomEvent(name, { - bubbles: true, - cancelable: true - }); - } else { - evt = document.createEvent('Event'); - evt.initEvent(name, true, true); - } - - evt.to = toEl || rootEl; - evt.from = fromEl || rootEl; - evt.item = targetEl || rootEl; - evt.clone = cloneEl; - evt.oldIndex = oldIndex; - evt.newIndex = newIndex; - evt.oldDraggableIndex = oldDraggableIndex; - evt.newDraggableIndex = newDraggableIndex; - evt.originalEvent = originalEvent; - evt.pullMode = putSortable ? putSortable.lastPutMode : undefined; - - var allEventProperties = _objectSpread2(_objectSpread2({}, extraEventProperties), PluginManager.getEventProperties(name, sortable)); - - for (var option in allEventProperties) { - evt[option] = allEventProperties[option]; - } - - if (rootEl) { - rootEl.dispatchEvent(evt); - } - - if (options[onName]) { - options[onName].call(sortable, evt); - } -} - -var _excluded = ["evt"]; - -var pluginEvent = function pluginEvent(eventName, sortable) { - var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, - originalEvent = _ref.evt, - data = _objectWithoutProperties(_ref, _excluded); - - PluginManager.pluginEvent.bind(Sortable)(eventName, sortable, _objectSpread2({ - dragEl: dragEl, - parentEl: parentEl, - ghostEl: ghostEl, - rootEl: rootEl, - nextEl: nextEl, - lastDownEl: lastDownEl, - cloneEl: cloneEl, - cloneHidden: cloneHidden, - dragStarted: moved, - putSortable: putSortable, - activeSortable: Sortable.active, - originalEvent: originalEvent, - oldIndex: oldIndex, - oldDraggableIndex: oldDraggableIndex, - newIndex: newIndex, - newDraggableIndex: newDraggableIndex, - hideGhostForTarget: _hideGhostForTarget, - unhideGhostForTarget: _unhideGhostForTarget, - cloneNowHidden: function cloneNowHidden() { - cloneHidden = true; - }, - cloneNowShown: function cloneNowShown() { - cloneHidden = false; - }, - dispatchSortableEvent: function dispatchSortableEvent(name) { - _dispatchEvent({ - sortable: sortable, - name: name, - originalEvent: originalEvent - }); - } - }, data)); -}; - -function _dispatchEvent(info) { - dispatchEvent(_objectSpread2({ - putSortable: putSortable, - cloneEl: cloneEl, - targetEl: dragEl, - rootEl: rootEl, - oldIndex: oldIndex, - oldDraggableIndex: oldDraggableIndex, - newIndex: newIndex, - newDraggableIndex: newDraggableIndex - }, info)); -} - -var dragEl, - parentEl, - ghostEl, - rootEl, - nextEl, - lastDownEl, - cloneEl, - cloneHidden, - oldIndex, - newIndex, - oldDraggableIndex, - newDraggableIndex, - activeGroup, - putSortable, - awaitingDragStarted = false, - ignoreNextClick = false, - sortables = [], - tapEvt, - touchEvt, - lastDx, - lastDy, - tapDistanceLeft, - tapDistanceTop, - moved, - lastTarget, - lastDirection, - pastFirstInvertThresh = false, - isCircumstantialInvert = false, - targetMoveDistance, - // For positioning ghost absolutely -ghostRelativeParent, - ghostRelativeParentInitialScroll = [], - // (left, top) -_silent = false, - savedInputChecked = []; -/** @const */ - -var documentExists = typeof document !== 'undefined', - PositionGhostAbsolutely = IOS, - CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float', - // This will not pass for IE9, because IE9 DnD only works on anchors -supportDraggable = documentExists && !ChromeForAndroid && !IOS && 'draggable' in document.createElement('div'), - supportCssPointerEvents = function () { - if (!documentExists) return; // false when <= IE11 - - if (IE11OrLess) { - return false; - } - - var el = document.createElement('x'); - el.style.cssText = 'pointer-events:auto'; - return el.style.pointerEvents === 'auto'; -}(), - _detectDirection = function _detectDirection(el, options) { - var elCSS = css(el), - elWidth = parseInt(elCSS.width) - parseInt(elCSS.paddingLeft) - parseInt(elCSS.paddingRight) - parseInt(elCSS.borderLeftWidth) - parseInt(elCSS.borderRightWidth), - child1 = getChild(el, 0, options), - child2 = getChild(el, 1, options), - firstChildCSS = child1 && css(child1), - secondChildCSS = child2 && css(child2), - firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width, - secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width; - - if (elCSS.display === 'flex') { - return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse' ? 'vertical' : 'horizontal'; - } - - if (elCSS.display === 'grid') { - return elCSS.gridTemplateColumns.split(' ').length <= 1 ? 'vertical' : 'horizontal'; - } - - if (child1 && firstChildCSS["float"] && firstChildCSS["float"] !== 'none') { - var touchingSideChild2 = firstChildCSS["float"] === 'left' ? 'left' : 'right'; - return child2 && (secondChildCSS.clear === 'both' || secondChildCSS.clear === touchingSideChild2) ? 'vertical' : 'horizontal'; - } - - return child1 && (firstChildCSS.display === 'block' || firstChildCSS.display === 'flex' || firstChildCSS.display === 'table' || firstChildCSS.display === 'grid' || firstChildWidth >= elWidth && elCSS[CSSFloatProperty] === 'none' || child2 && elCSS[CSSFloatProperty] === 'none' && firstChildWidth + secondChildWidth > elWidth) ? 'vertical' : 'horizontal'; -}, - _dragElInRowColumn = function _dragElInRowColumn(dragRect, targetRect, vertical) { - var dragElS1Opp = vertical ? dragRect.left : dragRect.top, - dragElS2Opp = vertical ? dragRect.right : dragRect.bottom, - dragElOppLength = vertical ? dragRect.width : dragRect.height, - targetS1Opp = vertical ? targetRect.left : targetRect.top, - targetS2Opp = vertical ? targetRect.right : targetRect.bottom, - targetOppLength = vertical ? targetRect.width : targetRect.height; - return dragElS1Opp === targetS1Opp || dragElS2Opp === targetS2Opp || dragElS1Opp + dragElOppLength / 2 === targetS1Opp + targetOppLength / 2; -}, - -/** - * Detects first nearest empty sortable to X and Y position using emptyInsertThreshold. - * @param {Number} x X position - * @param {Number} y Y position - * @return {HTMLElement} Element of the first found nearest Sortable - */ -_detectNearestEmptySortable = function _detectNearestEmptySortable(x, y) { - var ret; - sortables.some(function (sortable) { - var threshold = sortable[expando].options.emptyInsertThreshold; - if (!threshold || lastChild(sortable)) return; - var rect = getRect(sortable), - insideHorizontally = x >= rect.left - threshold && x <= rect.right + threshold, - insideVertically = y >= rect.top - threshold && y <= rect.bottom + threshold; - - if (insideHorizontally && insideVertically) { - return ret = sortable; - } - }); - return ret; -}, - _prepareGroup = function _prepareGroup(options) { - function toFn(value, pull) { - return function (to, from, dragEl, evt) { - var sameGroup = to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name; - - if (value == null && (pull || sameGroup)) { - // Default pull value - // Default pull and put value if same group - return true; - } else if (value == null || value === false) { - return false; - } else if (pull && value === 'clone') { - return value; - } else if (typeof value === 'function') { - return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt); - } else { - var otherGroup = (pull ? to : from).options.group.name; - return value === true || typeof value === 'string' && value === otherGroup || value.join && value.indexOf(otherGroup) > -1; - } - }; - } - - var group = {}; - var originalGroup = options.group; - - if (!originalGroup || _typeof(originalGroup) != 'object') { - originalGroup = { - name: originalGroup - }; - } - - group.name = originalGroup.name; - group.checkPull = toFn(originalGroup.pull, true); - group.checkPut = toFn(originalGroup.put); - group.revertClone = originalGroup.revertClone; - options.group = group; -}, - _hideGhostForTarget = function _hideGhostForTarget() { - if (!supportCssPointerEvents && ghostEl) { - css(ghostEl, 'display', 'none'); - } -}, - _unhideGhostForTarget = function _unhideGhostForTarget() { - if (!supportCssPointerEvents && ghostEl) { - css(ghostEl, 'display', ''); - } -}; // #1184 fix - Prevent click event on fallback if dragged but item not changed position - - -if (documentExists) { - document.addEventListener('click', function (evt) { - if (ignoreNextClick) { - evt.preventDefault(); - evt.stopPropagation && evt.stopPropagation(); - evt.stopImmediatePropagation && evt.stopImmediatePropagation(); - ignoreNextClick = false; - return false; - } - }, true); -} - -var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent(evt) { - if (dragEl) { - evt = evt.touches ? evt.touches[0] : evt; - - var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY); - - if (nearest) { - // Create imitation event - var event = {}; - - for (var i in evt) { - if (evt.hasOwnProperty(i)) { - event[i] = evt[i]; - } - } - - event.target = event.rootEl = nearest; - event.preventDefault = void 0; - event.stopPropagation = void 0; - - nearest[expando]._onDragOver(event); - } - } -}; - -var _checkOutsideTargetEl = function _checkOutsideTargetEl(evt) { - if (dragEl) { - dragEl.parentNode[expando]._isOutsideThisEl(evt.target); - } -}; -/** - * @class Sortable - * @param {HTMLElement} el - * @param {Object} [options] - */ - - -function Sortable(el, options) { - if (!(el && el.nodeType && el.nodeType === 1)) { - throw "Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(el)); - } - - this.el = el; // root element - - this.options = options = _extends({}, options); // Export instance - - el[expando] = this; - var defaults = { - group: null, - sort: true, - disabled: false, - store: null, - handle: null, - draggable: /^[uo]l$/i.test(el.nodeName) ? '>li' : '>*', - swapThreshold: 1, - // percentage; 0 <= x <= 1 - invertSwap: false, - // invert always - invertedSwapThreshold: null, - // will be set to same as swapThreshold if default - removeCloneOnHide: true, - direction: function direction() { - return _detectDirection(el, this.options); - }, - ghostClass: 'sortable-ghost', - chosenClass: 'sortable-chosen', - dragClass: 'sortable-drag', - ignore: 'a, img', - filter: null, - preventOnFilter: true, - animation: 0, - easing: null, - setData: function setData(dataTransfer, dragEl) { - dataTransfer.setData('Text', dragEl.textContent); - }, - dropBubble: false, - dragoverBubble: false, - dataIdAttr: 'data-id', - delay: 0, - delayOnTouchOnly: false, - touchStartThreshold: (Number.parseInt ? Number : window).parseInt(window.devicePixelRatio, 10) || 1, - forceFallback: false, - fallbackClass: 'sortable-fallback', - fallbackOnBody: false, - fallbackTolerance: 0, - fallbackOffset: { - x: 0, - y: 0 - }, - supportPointer: Sortable.supportPointer !== false && 'PointerEvent' in window && !Safari, - emptyInsertThreshold: 5 - }; - PluginManager.initializePlugins(this, el, defaults); // Set default options - - for (var name in defaults) { - !(name in options) && (options[name] = defaults[name]); - } - - _prepareGroup(options); // Bind all private methods - - - for (var fn in this) { - if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { - this[fn] = this[fn].bind(this); - } - } // Setup drag mode - - - this.nativeDraggable = options.forceFallback ? false : supportDraggable; - - if (this.nativeDraggable) { - // Touch start threshold cannot be greater than the native dragstart threshold - this.options.touchStartThreshold = 1; - } // Bind events - - - if (options.supportPointer) { - on(el, 'pointerdown', this._onTapStart); - } else { - on(el, 'mousedown', this._onTapStart); - on(el, 'touchstart', this._onTapStart); - } - - if (this.nativeDraggable) { - on(el, 'dragover', this); - on(el, 'dragenter', this); - } - - sortables.push(this.el); // Restore sorting - - options.store && options.store.get && this.sort(options.store.get(this) || []); // Add animation state manager - - _extends(this, AnimationStateManager()); -} - -Sortable.prototype = -/** @lends Sortable.prototype */ -{ - constructor: Sortable, - _isOutsideThisEl: function _isOutsideThisEl(target) { - if (!this.el.contains(target) && target !== this.el) { - lastTarget = null; - } - }, - _getDirection: function _getDirection(evt, target) { - return typeof this.options.direction === 'function' ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction; - }, - _onTapStart: function _onTapStart( - /** Event|TouchEvent */ - evt) { - if (!evt.cancelable) return; - - var _this = this, - el = this.el, - options = this.options, - preventOnFilter = options.preventOnFilter, - type = evt.type, - touch = evt.touches && evt.touches[0] || evt.pointerType && evt.pointerType === 'touch' && evt, - target = (touch || evt).target, - originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0] || evt.composedPath && evt.composedPath()[0]) || target, - filter = options.filter; - - _saveInputCheckedState(el); // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group. - - - if (dragEl) { - return; - } - - if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) { - return; // only left button and enabled - } // cancel dnd if original target is content editable - - - if (originalTarget.isContentEditable) { - return; - } // Safari ignores further event handling after mousedown - - - if (!this.nativeDraggable && Safari && target && target.tagName.toUpperCase() === 'SELECT') { - return; - } - - target = closest(target, options.draggable, el, false); - - if (target && target.animated) { - return; - } - - if (lastDownEl === target) { - // Ignoring duplicate `down` - return; - } // Get the index of the dragged element within its parent - - - oldIndex = index(target); - oldDraggableIndex = index(target, options.draggable); // Check filter - - if (typeof filter === 'function') { - if (filter.call(this, evt, target, this)) { - _dispatchEvent({ - sortable: _this, - rootEl: originalTarget, - name: 'filter', - targetEl: target, - toEl: el, - fromEl: el - }); - - pluginEvent('filter', _this, { - evt: evt - }); - preventOnFilter && evt.cancelable && evt.preventDefault(); - return; // cancel dnd - } - } else if (filter) { - filter = filter.split(',').some(function (criteria) { - criteria = closest(originalTarget, criteria.trim(), el, false); - - if (criteria) { - _dispatchEvent({ - sortable: _this, - rootEl: criteria, - name: 'filter', - targetEl: target, - fromEl: el, - toEl: el - }); - - pluginEvent('filter', _this, { - evt: evt - }); - return true; - } - }); - - if (filter) { - preventOnFilter && evt.cancelable && evt.preventDefault(); - return; // cancel dnd - } - } - - if (options.handle && !closest(originalTarget, options.handle, el, false)) { - return; - } // Prepare `dragstart` - - - this._prepareDragStart(evt, touch, target); - }, - _prepareDragStart: function _prepareDragStart( - /** Event */ - evt, - /** Touch */ - touch, - /** HTMLElement */ - target) { - var _this = this, - el = _this.el, - options = _this.options, - ownerDocument = el.ownerDocument, - dragStartFn; - - if (target && !dragEl && target.parentNode === el) { - var dragRect = getRect(target); - rootEl = el; - dragEl = target; - parentEl = dragEl.parentNode; - nextEl = dragEl.nextSibling; - lastDownEl = target; - activeGroup = options.group; - Sortable.dragged = dragEl; - tapEvt = { - target: dragEl, - clientX: (touch || evt).clientX, - clientY: (touch || evt).clientY - }; - tapDistanceLeft = tapEvt.clientX - dragRect.left; - tapDistanceTop = tapEvt.clientY - dragRect.top; - this._lastX = (touch || evt).clientX; - this._lastY = (touch || evt).clientY; - dragEl.style['will-change'] = 'all'; - - dragStartFn = function dragStartFn() { - pluginEvent('delayEnded', _this, { - evt: evt - }); - - if (Sortable.eventCanceled) { - _this._onDrop(); - - return; - } // Delayed drag has been triggered - // we can re-enable the events: touchmove/mousemove - - - _this._disableDelayedDragEvents(); - - if (!FireFox && _this.nativeDraggable) { - dragEl.draggable = true; - } // Bind the events: dragstart/dragend - - - _this._triggerDragStart(evt, touch); // Drag start event - - - _dispatchEvent({ - sortable: _this, - name: 'choose', - originalEvent: evt - }); // Chosen item - - - toggleClass(dragEl, options.chosenClass, true); - }; // Disable "draggable" - - - options.ignore.split(',').forEach(function (criteria) { - find(dragEl, criteria.trim(), _disableDraggable); - }); - on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent); - on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent); - on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent); - on(ownerDocument, 'mouseup', _this._onDrop); - on(ownerDocument, 'touchend', _this._onDrop); - on(ownerDocument, 'touchcancel', _this._onDrop); // Make dragEl draggable (must be before delay for FireFox) - - if (FireFox && this.nativeDraggable) { - this.options.touchStartThreshold = 4; - dragEl.draggable = true; - } - - pluginEvent('delayStart', this, { - evt: evt - }); // Delay is impossible for native DnD in Edge or IE - - if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) { - if (Sortable.eventCanceled) { - this._onDrop(); - - return; - } // If the user moves the pointer or let go the click or touch - // before the delay has been reached: - // disable the delayed drag - - - on(ownerDocument, 'mouseup', _this._disableDelayedDrag); - on(ownerDocument, 'touchend', _this._disableDelayedDrag); - on(ownerDocument, 'touchcancel', _this._disableDelayedDrag); - on(ownerDocument, 'mousemove', _this._delayedDragTouchMoveHandler); - on(ownerDocument, 'touchmove', _this._delayedDragTouchMoveHandler); - options.supportPointer && on(ownerDocument, 'pointermove', _this._delayedDragTouchMoveHandler); - _this._dragStartTimer = setTimeout(dragStartFn, options.delay); - } else { - dragStartFn(); - } - } - }, - _delayedDragTouchMoveHandler: function _delayedDragTouchMoveHandler( - /** TouchEvent|PointerEvent **/ - e) { - var touch = e.touches ? e.touches[0] : e; - - if (Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1))) { - this._disableDelayedDrag(); - } - }, - _disableDelayedDrag: function _disableDelayedDrag() { - dragEl && _disableDraggable(dragEl); - clearTimeout(this._dragStartTimer); - - this._disableDelayedDragEvents(); - }, - _disableDelayedDragEvents: function _disableDelayedDragEvents() { - var ownerDocument = this.el.ownerDocument; - off(ownerDocument, 'mouseup', this._disableDelayedDrag); - off(ownerDocument, 'touchend', this._disableDelayedDrag); - off(ownerDocument, 'touchcancel', this._disableDelayedDrag); - off(ownerDocument, 'mousemove', this._delayedDragTouchMoveHandler); - off(ownerDocument, 'touchmove', this._delayedDragTouchMoveHandler); - off(ownerDocument, 'pointermove', this._delayedDragTouchMoveHandler); - }, - _triggerDragStart: function _triggerDragStart( - /** Event */ - evt, - /** Touch */ - touch) { - touch = touch || evt.pointerType == 'touch' && evt; - - if (!this.nativeDraggable || touch) { - if (this.options.supportPointer) { - on(document, 'pointermove', this._onTouchMove); - } else if (touch) { - on(document, 'touchmove', this._onTouchMove); - } else { - on(document, 'mousemove', this._onTouchMove); - } - } else { - on(dragEl, 'dragend', this); - on(rootEl, 'dragstart', this._onDragStart); - } - - try { - if (document.selection) { - // Timeout neccessary for IE9 - _nextTick(function () { - document.selection.empty(); - }); - } else { - window.getSelection().removeAllRanges(); - } - } catch (err) {} - }, - _dragStarted: function _dragStarted(fallback, evt) { - - awaitingDragStarted = false; - - if (rootEl && dragEl) { - pluginEvent('dragStarted', this, { - evt: evt - }); - - if (this.nativeDraggable) { - on(document, 'dragover', _checkOutsideTargetEl); - } - - var options = this.options; // Apply effect - - !fallback && toggleClass(dragEl, options.dragClass, false); - toggleClass(dragEl, options.ghostClass, true); - Sortable.active = this; - fallback && this._appendGhost(); // Drag start event - - _dispatchEvent({ - sortable: this, - name: 'start', - originalEvent: evt - }); - } else { - this._nulling(); - } - }, - _emulateDragOver: function _emulateDragOver() { - if (touchEvt) { - this._lastX = touchEvt.clientX; - this._lastY = touchEvt.clientY; - - _hideGhostForTarget(); - - var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY); - var parent = target; - - while (target && target.shadowRoot) { - target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY); - if (target === parent) break; - parent = target; - } - - dragEl.parentNode[expando]._isOutsideThisEl(target); - - if (parent) { - do { - if (parent[expando]) { - var inserted = void 0; - inserted = parent[expando]._onDragOver({ - clientX: touchEvt.clientX, - clientY: touchEvt.clientY, - target: target, - rootEl: parent - }); - - if (inserted && !this.options.dragoverBubble) { - break; - } - } - - target = parent; // store last element - } - /* jshint boss:true */ - while (parent = parent.parentNode); - } - - _unhideGhostForTarget(); - } - }, - _onTouchMove: function _onTouchMove( - /**TouchEvent*/ - evt) { - if (tapEvt) { - var options = this.options, - fallbackTolerance = options.fallbackTolerance, - fallbackOffset = options.fallbackOffset, - touch = evt.touches ? evt.touches[0] : evt, - ghostMatrix = ghostEl && matrix(ghostEl, true), - scaleX = ghostEl && ghostMatrix && ghostMatrix.a, - scaleY = ghostEl && ghostMatrix && ghostMatrix.d, - relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent), - dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1), - dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1); // only set the status to dragging, when we are actually dragging - - if (!Sortable.active && !awaitingDragStarted) { - if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) { - return; - } - - this._onDragStart(evt, true); - } - - if (ghostEl) { - if (ghostMatrix) { - ghostMatrix.e += dx - (lastDx || 0); - ghostMatrix.f += dy - (lastDy || 0); - } else { - ghostMatrix = { - a: 1, - b: 0, - c: 0, - d: 1, - e: dx, - f: dy - }; - } - - var cssMatrix = "matrix(".concat(ghostMatrix.a, ",").concat(ghostMatrix.b, ",").concat(ghostMatrix.c, ",").concat(ghostMatrix.d, ",").concat(ghostMatrix.e, ",").concat(ghostMatrix.f, ")"); - css(ghostEl, 'webkitTransform', cssMatrix); - css(ghostEl, 'mozTransform', cssMatrix); - css(ghostEl, 'msTransform', cssMatrix); - css(ghostEl, 'transform', cssMatrix); - lastDx = dx; - lastDy = dy; - touchEvt = touch; - } - - evt.cancelable && evt.preventDefault(); - } - }, - _appendGhost: function _appendGhost() { - // Bug if using scale(): https://stackoverflow.com/questions/2637058 - // Not being adjusted for - if (!ghostEl) { - var container = this.options.fallbackOnBody ? document.body : rootEl, - rect = getRect(dragEl, true, PositionGhostAbsolutely, true, container), - options = this.options; // Position absolutely - - if (PositionGhostAbsolutely) { - // Get relatively positioned parent - ghostRelativeParent = container; - - while (css(ghostRelativeParent, 'position') === 'static' && css(ghostRelativeParent, 'transform') === 'none' && ghostRelativeParent !== document) { - ghostRelativeParent = ghostRelativeParent.parentNode; - } - - if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) { - if (ghostRelativeParent === document) ghostRelativeParent = getWindowScrollingElement(); - rect.top += ghostRelativeParent.scrollTop; - rect.left += ghostRelativeParent.scrollLeft; - } else { - ghostRelativeParent = getWindowScrollingElement(); - } - - ghostRelativeParentInitialScroll = getRelativeScrollOffset(ghostRelativeParent); - } - - ghostEl = dragEl.cloneNode(true); - toggleClass(ghostEl, options.ghostClass, false); - toggleClass(ghostEl, options.fallbackClass, true); - toggleClass(ghostEl, options.dragClass, true); - css(ghostEl, 'transition', ''); - css(ghostEl, 'transform', ''); - css(ghostEl, 'box-sizing', 'border-box'); - css(ghostEl, 'margin', 0); - css(ghostEl, 'top', rect.top); - css(ghostEl, 'left', rect.left); - css(ghostEl, 'width', rect.width); - css(ghostEl, 'height', rect.height); - css(ghostEl, 'opacity', '0.8'); - css(ghostEl, 'position', PositionGhostAbsolutely ? 'absolute' : 'fixed'); - css(ghostEl, 'zIndex', '100000'); - css(ghostEl, 'pointerEvents', 'none'); - Sortable.ghost = ghostEl; - container.appendChild(ghostEl); // Set transform-origin - - css(ghostEl, 'transform-origin', tapDistanceLeft / parseInt(ghostEl.style.width) * 100 + '% ' + tapDistanceTop / parseInt(ghostEl.style.height) * 100 + '%'); - } - }, - _onDragStart: function _onDragStart( - /**Event*/ - evt, - /**boolean*/ - fallback) { - var _this = this; - - var dataTransfer = evt.dataTransfer; - var options = _this.options; - pluginEvent('dragStart', this, { - evt: evt - }); - - if (Sortable.eventCanceled) { - this._onDrop(); - - return; - } - - pluginEvent('setupClone', this); - - if (!Sortable.eventCanceled) { - cloneEl = clone(dragEl); - cloneEl.draggable = false; - cloneEl.style['will-change'] = ''; - - this._hideClone(); - - toggleClass(cloneEl, this.options.chosenClass, false); - Sortable.clone = cloneEl; - } // #1143: IFrame support workaround - - - _this.cloneId = _nextTick(function () { - pluginEvent('clone', _this); - if (Sortable.eventCanceled) return; - - if (!_this.options.removeCloneOnHide) { - rootEl.insertBefore(cloneEl, dragEl); - } - - _this._hideClone(); - - _dispatchEvent({ - sortable: _this, - name: 'clone' - }); - }); - !fallback && toggleClass(dragEl, options.dragClass, true); // Set proper drop events - - if (fallback) { - ignoreNextClick = true; - _this._loopId = setInterval(_this._emulateDragOver, 50); - } else { - // Undo what was set in _prepareDragStart before drag started - off(document, 'mouseup', _this._onDrop); - off(document, 'touchend', _this._onDrop); - off(document, 'touchcancel', _this._onDrop); - - if (dataTransfer) { - dataTransfer.effectAllowed = 'move'; - options.setData && options.setData.call(_this, dataTransfer, dragEl); - } - - on(document, 'drop', _this); // #1276 fix: - - css(dragEl, 'transform', 'translateZ(0)'); - } - - awaitingDragStarted = true; - _this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt)); - on(document, 'selectstart', _this); - moved = true; - - if (Safari) { - css(document.body, 'user-select', 'none'); - } - }, - // Returns true - if no further action is needed (either inserted or another condition) - _onDragOver: function _onDragOver( - /**Event*/ - evt) { - var el = this.el, - target = evt.target, - dragRect, - targetRect, - revert, - options = this.options, - group = options.group, - activeSortable = Sortable.active, - isOwner = activeGroup === group, - canSort = options.sort, - fromSortable = putSortable || activeSortable, - vertical, - _this = this, - completedFired = false; - - if (_silent) return; - - function dragOverEvent(name, extra) { - pluginEvent(name, _this, _objectSpread2({ - evt: evt, - isOwner: isOwner, - axis: vertical ? 'vertical' : 'horizontal', - revert: revert, - dragRect: dragRect, - targetRect: targetRect, - canSort: canSort, - fromSortable: fromSortable, - target: target, - completed: completed, - onMove: function onMove(target, after) { - return _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after); - }, - changed: changed - }, extra)); - } // Capture animation state - - - function capture() { - dragOverEvent('dragOverAnimationCapture'); - - _this.captureAnimationState(); - - if (_this !== fromSortable) { - fromSortable.captureAnimationState(); - } - } // Return invocation when dragEl is inserted (or completed) - - - function completed(insertion) { - dragOverEvent('dragOverCompleted', { - insertion: insertion - }); - - if (insertion) { - // Clones must be hidden before folding animation to capture dragRectAbsolute properly - if (isOwner) { - activeSortable._hideClone(); - } else { - activeSortable._showClone(_this); - } - - if (_this !== fromSortable) { - // Set ghost class to new sortable's ghost class - toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false); - toggleClass(dragEl, options.ghostClass, true); - } - - if (putSortable !== _this && _this !== Sortable.active) { - putSortable = _this; - } else if (_this === Sortable.active && putSortable) { - putSortable = null; - } // Animation - - - if (fromSortable === _this) { - _this._ignoreWhileAnimating = target; - } - - _this.animateAll(function () { - dragOverEvent('dragOverAnimationComplete'); - _this._ignoreWhileAnimating = null; - }); - - if (_this !== fromSortable) { - fromSortable.animateAll(); - fromSortable._ignoreWhileAnimating = null; - } - } // Null lastTarget if it is not inside a previously swapped element - - - if (target === dragEl && !dragEl.animated || target === el && !target.animated) { - lastTarget = null; - } // no bubbling and not fallback - - - if (!options.dragoverBubble && !evt.rootEl && target !== document) { - dragEl.parentNode[expando]._isOutsideThisEl(evt.target); // Do not detect for empty insert if already inserted - - - !insertion && nearestEmptyInsertDetectEvent(evt); - } - - !options.dragoverBubble && evt.stopPropagation && evt.stopPropagation(); - return completedFired = true; - } // Call when dragEl has been inserted - - - function changed() { - newIndex = index(dragEl); - newDraggableIndex = index(dragEl, options.draggable); - - _dispatchEvent({ - sortable: _this, - name: 'change', - toEl: el, - newIndex: newIndex, - newDraggableIndex: newDraggableIndex, - originalEvent: evt - }); - } - - if (evt.preventDefault !== void 0) { - evt.cancelable && evt.preventDefault(); - } - - target = closest(target, options.draggable, el, true); - dragOverEvent('dragOver'); - if (Sortable.eventCanceled) return completedFired; - - if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) { - return completed(false); - } - - ignoreNextClick = false; - - if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = parentEl !== rootEl) // Reverting item into the original list - : putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) { - vertical = this._getDirection(evt, target) === 'vertical'; - dragRect = getRect(dragEl); - dragOverEvent('dragOverValid'); - if (Sortable.eventCanceled) return completedFired; - - if (revert) { - parentEl = rootEl; // actualization - - capture(); - - this._hideClone(); - - dragOverEvent('revert'); - - if (!Sortable.eventCanceled) { - if (nextEl) { - rootEl.insertBefore(dragEl, nextEl); - } else { - rootEl.appendChild(dragEl); - } - } - - return completed(true); - } - - var elLastChild = lastChild(el, options.draggable); - - if (!elLastChild || _ghostIsLast(evt, vertical, this) && !elLastChild.animated) { - // Insert to end of list - // If already at end of list: Do not insert - if (elLastChild === dragEl) { - return completed(false); - } // if there is a last element, it is the target - - - if (elLastChild && el === evt.target) { - target = elLastChild; - } - - if (target) { - targetRect = getRect(target); - } - - if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) { - capture(); - el.appendChild(dragEl); - parentEl = el; // actualization - - changed(); - return completed(true); - } - } else if (elLastChild && _ghostIsFirst(evt, vertical, this)) { - // Insert to start of list - var firstChild = getChild(el, 0, options, true); - - if (firstChild === dragEl) { - return completed(false); - } - - target = firstChild; - targetRect = getRect(target); - - if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, false) !== false) { - capture(); - el.insertBefore(dragEl, firstChild); - parentEl = el; // actualization - - changed(); - return completed(true); - } - } else if (target.parentNode === el) { - targetRect = getRect(target); - var direction = 0, - targetBeforeFirstSwap, - differentLevel = dragEl.parentNode !== el, - differentRowCol = !_dragElInRowColumn(dragEl.animated && dragEl.toRect || dragRect, target.animated && target.toRect || targetRect, vertical), - side1 = vertical ? 'top' : 'left', - scrolledPastTop = isScrolledPast(target, 'top', 'top') || isScrolledPast(dragEl, 'top', 'top'), - scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0; - - if (lastTarget !== target) { - targetBeforeFirstSwap = targetRect[side1]; - pastFirstInvertThresh = false; - isCircumstantialInvert = !differentRowCol && options.invertSwap || differentLevel; - } - - direction = _getSwapDirection(evt, target, targetRect, vertical, differentRowCol ? 1 : options.swapThreshold, options.invertedSwapThreshold == null ? options.swapThreshold : options.invertedSwapThreshold, isCircumstantialInvert, lastTarget === target); - var sibling; - - if (direction !== 0) { - // Check if target is beside dragEl in respective direction (ignoring hidden elements) - var dragIndex = index(dragEl); - - do { - dragIndex -= direction; - sibling = parentEl.children[dragIndex]; - } while (sibling && (css(sibling, 'display') === 'none' || sibling === ghostEl)); - } // If dragEl is already beside target: Do not insert - - - if (direction === 0 || sibling === target) { - return completed(false); - } - - lastTarget = target; - lastDirection = direction; - var nextSibling = target.nextElementSibling, - after = false; - after = direction === 1; - - var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after); - - if (moveVector !== false) { - if (moveVector === 1 || moveVector === -1) { - after = moveVector === 1; - } - - _silent = true; - setTimeout(_unsilent, 30); - capture(); - - if (after && !nextSibling) { - el.appendChild(dragEl); - } else { - target.parentNode.insertBefore(dragEl, after ? nextSibling : target); - } // Undo chrome's scroll adjustment (has no effect on other browsers) - - - if (scrolledPastTop) { - scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop); - } - - parentEl = dragEl.parentNode; // actualization - // must be done before animation - - if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) { - targetMoveDistance = Math.abs(targetBeforeFirstSwap - getRect(target)[side1]); - } - - changed(); - return completed(true); - } - } - - if (el.contains(dragEl)) { - return completed(false); - } - } - - return false; - }, - _ignoreWhileAnimating: null, - _offMoveEvents: function _offMoveEvents() { - off(document, 'mousemove', this._onTouchMove); - off(document, 'touchmove', this._onTouchMove); - off(document, 'pointermove', this._onTouchMove); - off(document, 'dragover', nearestEmptyInsertDetectEvent); - off(document, 'mousemove', nearestEmptyInsertDetectEvent); - off(document, 'touchmove', nearestEmptyInsertDetectEvent); - }, - _offUpEvents: function _offUpEvents() { - var ownerDocument = this.el.ownerDocument; - off(ownerDocument, 'mouseup', this._onDrop); - off(ownerDocument, 'touchend', this._onDrop); - off(ownerDocument, 'pointerup', this._onDrop); - off(ownerDocument, 'touchcancel', this._onDrop); - off(document, 'selectstart', this); - }, - _onDrop: function _onDrop( - /**Event*/ - evt) { - var el = this.el, - options = this.options; // Get the index of the dragged element within its parent - - newIndex = index(dragEl); - newDraggableIndex = index(dragEl, options.draggable); - pluginEvent('drop', this, { - evt: evt - }); - parentEl = dragEl && dragEl.parentNode; // Get again after plugin event - - newIndex = index(dragEl); - newDraggableIndex = index(dragEl, options.draggable); - - if (Sortable.eventCanceled) { - this._nulling(); - - return; - } - - awaitingDragStarted = false; - isCircumstantialInvert = false; - pastFirstInvertThresh = false; - clearInterval(this._loopId); - clearTimeout(this._dragStartTimer); - - _cancelNextTick(this.cloneId); - - _cancelNextTick(this._dragStartId); // Unbind events - - - if (this.nativeDraggable) { - off(document, 'drop', this); - off(el, 'dragstart', this._onDragStart); - } - - this._offMoveEvents(); - - this._offUpEvents(); - - if (Safari) { - css(document.body, 'user-select', ''); - } - - css(dragEl, 'transform', ''); - - if (evt) { - if (moved) { - evt.cancelable && evt.preventDefault(); - !options.dropBubble && evt.stopPropagation(); - } - - ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl); - - if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') { - // Remove clone(s) - cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl); - } - - if (dragEl) { - if (this.nativeDraggable) { - off(dragEl, 'dragend', this); - } - - _disableDraggable(dragEl); - - dragEl.style['will-change'] = ''; // Remove classes - // ghostClass is added in dragStarted - - if (moved && !awaitingDragStarted) { - toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : this.options.ghostClass, false); - } - - toggleClass(dragEl, this.options.chosenClass, false); // Drag stop event - - _dispatchEvent({ - sortable: this, - name: 'unchoose', - toEl: parentEl, - newIndex: null, - newDraggableIndex: null, - originalEvent: evt - }); - - if (rootEl !== parentEl) { - if (newIndex >= 0) { - // Add event - _dispatchEvent({ - rootEl: parentEl, - name: 'add', - toEl: parentEl, - fromEl: rootEl, - originalEvent: evt - }); // Remove event - - - _dispatchEvent({ - sortable: this, - name: 'remove', - toEl: parentEl, - originalEvent: evt - }); // drag from one list and drop into another - - - _dispatchEvent({ - rootEl: parentEl, - name: 'sort', - toEl: parentEl, - fromEl: rootEl, - originalEvent: evt - }); - - _dispatchEvent({ - sortable: this, - name: 'sort', - toEl: parentEl, - originalEvent: evt - }); - } - - putSortable && putSortable.save(); - } else { - if (newIndex !== oldIndex) { - if (newIndex >= 0) { - // drag & drop within the same list - _dispatchEvent({ - sortable: this, - name: 'update', - toEl: parentEl, - originalEvent: evt - }); - - _dispatchEvent({ - sortable: this, - name: 'sort', - toEl: parentEl, - originalEvent: evt - }); - } - } - } - - if (Sortable.active) { - /* jshint eqnull:true */ - if (newIndex == null || newIndex === -1) { - newIndex = oldIndex; - newDraggableIndex = oldDraggableIndex; - } - - _dispatchEvent({ - sortable: this, - name: 'end', - toEl: parentEl, - originalEvent: evt - }); // Save sorting - - - this.save(); - } - } - } - - this._nulling(); - }, - _nulling: function _nulling() { - pluginEvent('nulling', this); - rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable.dragged = Sortable.ghost = Sortable.clone = Sortable.active = null; - savedInputChecked.forEach(function (el) { - el.checked = true; - }); - savedInputChecked.length = lastDx = lastDy = 0; - }, - handleEvent: function handleEvent( - /**Event*/ - evt) { - switch (evt.type) { - case 'drop': - case 'dragend': - this._onDrop(evt); - - break; - - case 'dragenter': - case 'dragover': - if (dragEl) { - this._onDragOver(evt); - - _globalDragOver(evt); - } - - break; - - case 'selectstart': - evt.preventDefault(); - break; - } - }, - - /** - * Serializes the item into an array of string. - * @returns {String[]} - */ - toArray: function toArray() { - var order = [], - el, - children = this.el.children, - i = 0, - n = children.length, - options = this.options; - - for (; i < n; i++) { - el = children[i]; - - if (closest(el, options.draggable, this.el, false)) { - order.push(el.getAttribute(options.dataIdAttr) || _generateId(el)); - } - } - - return order; - }, - - /** - * Sorts the elements according to the array. - * @param {String[]} order order of the items - */ - sort: function sort(order, useAnimation) { - var items = {}, - rootEl = this.el; - this.toArray().forEach(function (id, i) { - var el = rootEl.children[i]; - - if (closest(el, this.options.draggable, rootEl, false)) { - items[id] = el; - } - }, this); - useAnimation && this.captureAnimationState(); - order.forEach(function (id) { - if (items[id]) { - rootEl.removeChild(items[id]); - rootEl.appendChild(items[id]); - } - }); - useAnimation && this.animateAll(); - }, - - /** - * Save the current sorting - */ - save: function save() { - var store = this.options.store; - store && store.set && store.set(this); - }, - - /** - * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. - * @param {HTMLElement} el - * @param {String} [selector] default: `options.draggable` - * @returns {HTMLElement|null} - */ - closest: function closest$1(el, selector) { - return closest(el, selector || this.options.draggable, this.el, false); - }, - - /** - * Set/get option - * @param {string} name - * @param {*} [value] - * @returns {*} - */ - option: function option(name, value) { - var options = this.options; - - if (value === void 0) { - return options[name]; - } else { - var modifiedValue = PluginManager.modifyOption(this, name, value); - - if (typeof modifiedValue !== 'undefined') { - options[name] = modifiedValue; - } else { - options[name] = value; - } - - if (name === 'group') { - _prepareGroup(options); - } - } - }, - - /** - * Destroy - */ - destroy: function destroy() { - pluginEvent('destroy', this); - var el = this.el; - el[expando] = null; - off(el, 'mousedown', this._onTapStart); - off(el, 'touchstart', this._onTapStart); - off(el, 'pointerdown', this._onTapStart); - - if (this.nativeDraggable) { - off(el, 'dragover', this); - off(el, 'dragenter', this); - } // Remove draggable attributes - - - Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) { - el.removeAttribute('draggable'); - }); - - this._onDrop(); - - this._disableDelayedDragEvents(); - - sortables.splice(sortables.indexOf(this.el), 1); - this.el = el = null; - }, - _hideClone: function _hideClone() { - if (!cloneHidden) { - pluginEvent('hideClone', this); - if (Sortable.eventCanceled) return; - css(cloneEl, 'display', 'none'); - - if (this.options.removeCloneOnHide && cloneEl.parentNode) { - cloneEl.parentNode.removeChild(cloneEl); - } - - cloneHidden = true; - } - }, - _showClone: function _showClone(putSortable) { - if (putSortable.lastPutMode !== 'clone') { - this._hideClone(); - - return; - } - - if (cloneHidden) { - pluginEvent('showClone', this); - if (Sortable.eventCanceled) return; // show clone at dragEl or original position - - if (dragEl.parentNode == rootEl && !this.options.group.revertClone) { - rootEl.insertBefore(cloneEl, dragEl); - } else if (nextEl) { - rootEl.insertBefore(cloneEl, nextEl); - } else { - rootEl.appendChild(cloneEl); - } - - if (this.options.group.revertClone) { - this.animate(dragEl, cloneEl); - } - - css(cloneEl, 'display', ''); - cloneHidden = false; - } - } -}; - -function _globalDragOver( -/**Event*/ -evt) { - if (evt.dataTransfer) { - evt.dataTransfer.dropEffect = 'move'; - } - - evt.cancelable && evt.preventDefault(); -} - -function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) { - var evt, - sortable = fromEl[expando], - onMoveFn = sortable.options.onMove, - retVal; // Support for new CustomEvent feature - - if (window.CustomEvent && !IE11OrLess && !Edge) { - evt = new CustomEvent('move', { - bubbles: true, - cancelable: true - }); - } else { - evt = document.createEvent('Event'); - evt.initEvent('move', true, true); - } - - evt.to = toEl; - evt.from = fromEl; - evt.dragged = dragEl; - evt.draggedRect = dragRect; - evt.related = targetEl || toEl; - evt.relatedRect = targetRect || getRect(toEl); - evt.willInsertAfter = willInsertAfter; - evt.originalEvent = originalEvent; - fromEl.dispatchEvent(evt); - - if (onMoveFn) { - retVal = onMoveFn.call(sortable, evt, originalEvent); - } - - return retVal; -} - -function _disableDraggable(el) { - el.draggable = false; -} - -function _unsilent() { - _silent = false; -} - -function _ghostIsFirst(evt, vertical, sortable) { - var rect = getRect(getChild(sortable.el, 0, sortable.options, true)); - var spacer = 10; - return vertical ? evt.clientX < rect.left - spacer || evt.clientY < rect.top && evt.clientX < rect.right : evt.clientY < rect.top - spacer || evt.clientY < rect.bottom && evt.clientX < rect.left; -} - -function _ghostIsLast(evt, vertical, sortable) { - var rect = getRect(lastChild(sortable.el, sortable.options.draggable)); - var spacer = 10; - return vertical ? evt.clientX > rect.right + spacer || evt.clientX <= rect.right && evt.clientY > rect.bottom && evt.clientX >= rect.left : evt.clientX > rect.right && evt.clientY > rect.top || evt.clientX <= rect.right && evt.clientY > rect.bottom + spacer; -} - -function _getSwapDirection(evt, target, targetRect, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) { - var mouseOnAxis = vertical ? evt.clientY : evt.clientX, - targetLength = vertical ? targetRect.height : targetRect.width, - targetS1 = vertical ? targetRect.top : targetRect.left, - targetS2 = vertical ? targetRect.bottom : targetRect.right, - invert = false; - - if (!invertSwap) { - // Never invert or create dragEl shadow when target movemenet causes mouse to move past the end of regular swapThreshold - if (isLastTarget && targetMoveDistance < targetLength * swapThreshold) { - // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2 - // check if past first invert threshold on side opposite of lastDirection - if (!pastFirstInvertThresh && (lastDirection === 1 ? mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2 : mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2)) { - // past first invert threshold, do not restrict inverted threshold to dragEl shadow - pastFirstInvertThresh = true; - } - - if (!pastFirstInvertThresh) { - // dragEl shadow (target move distance shadow) - if (lastDirection === 1 ? mouseOnAxis < targetS1 + targetMoveDistance // over dragEl shadow - : mouseOnAxis > targetS2 - targetMoveDistance) { - return -lastDirection; - } - } else { - invert = true; - } - } else { - // Regular - if (mouseOnAxis > targetS1 + targetLength * (1 - swapThreshold) / 2 && mouseOnAxis < targetS2 - targetLength * (1 - swapThreshold) / 2) { - return _getInsertDirection(target); - } - } - } - - invert = invert || invertSwap; - - if (invert) { - // Invert of regular - if (mouseOnAxis < targetS1 + targetLength * invertedSwapThreshold / 2 || mouseOnAxis > targetS2 - targetLength * invertedSwapThreshold / 2) { - return mouseOnAxis > targetS1 + targetLength / 2 ? 1 : -1; - } - } - - return 0; -} -/** - * Gets the direction dragEl must be swapped relative to target in order to make it - * seem that dragEl has been "inserted" into that element's position - * @param {HTMLElement} target The target whose position dragEl is being inserted at - * @return {Number} Direction dragEl must be swapped - */ - - -function _getInsertDirection(target) { - if (index(dragEl) < index(target)) { - return 1; - } else { - return -1; - } -} -/** - * Generate id - * @param {HTMLElement} el - * @returns {String} - * @private - */ - - -function _generateId(el) { - var str = el.tagName + el.className + el.src + el.href + el.textContent, - i = str.length, - sum = 0; - - while (i--) { - sum += str.charCodeAt(i); - } - - return sum.toString(36); -} - -function _saveInputCheckedState(root) { - savedInputChecked.length = 0; - var inputs = root.getElementsByTagName('input'); - var idx = inputs.length; - - while (idx--) { - var el = inputs[idx]; - el.checked && savedInputChecked.push(el); - } -} - -function _nextTick(fn) { - return setTimeout(fn, 0); -} - -function _cancelNextTick(id) { - return clearTimeout(id); -} // Fixed #973: - - -if (documentExists) { - on(document, 'touchmove', function (evt) { - if ((Sortable.active || awaitingDragStarted) && evt.cancelable) { - evt.preventDefault(); - } - }); -} // Export utils - - -Sortable.utils = { - on: on, - off: off, - css: css, - find: find, - is: function is(el, selector) { - return !!closest(el, selector, el, false); - }, - extend: extend, - throttle: throttle, - closest: closest, - toggleClass: toggleClass, - clone: clone, - index: index, - nextTick: _nextTick, - cancelNextTick: _cancelNextTick, - detectDirection: _detectDirection, - getChild: getChild -}; -/** - * Get the Sortable instance of an element - * @param {HTMLElement} element The element - * @return {Sortable|undefined} The instance of Sortable - */ - -Sortable.get = function (element) { - return element[expando]; -}; -/** - * Mount a plugin to Sortable - * @param {...SortablePlugin|SortablePlugin[]} plugins Plugins being mounted - */ - - -Sortable.mount = function () { - for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) { - plugins[_key] = arguments[_key]; - } - - if (plugins[0].constructor === Array) plugins = plugins[0]; - plugins.forEach(function (plugin) { - if (!plugin.prototype || !plugin.prototype.constructor) { - throw "Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(plugin)); - } - - if (plugin.utils) Sortable.utils = _objectSpread2(_objectSpread2({}, Sortable.utils), plugin.utils); - PluginManager.mount(plugin); - }); -}; -/** - * Create sortable instance - * @param {HTMLElement} el - * @param {Object} [options] - */ - - -Sortable.create = function (el, options) { - return new Sortable(el, options); -}; // Export - - -Sortable.version = version$1; - -var autoScrolls = [], - scrollEl, - scrollRootEl, - scrolling = false, - lastAutoScrollX, - lastAutoScrollY, - touchEvt$1, - pointerElemChangedInterval; - -function AutoScrollPlugin() { - function AutoScroll() { - this.defaults = { - scroll: true, - forceAutoScrollFallback: false, - scrollSensitivity: 30, - scrollSpeed: 10, - bubbleScroll: true - }; // Bind all private methods - - for (var fn in this) { - if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { - this[fn] = this[fn].bind(this); - } - } - } - - AutoScroll.prototype = { - dragStarted: function dragStarted(_ref) { - var originalEvent = _ref.originalEvent; - - if (this.sortable.nativeDraggable) { - on(document, 'dragover', this._handleAutoScroll); - } else { - if (this.options.supportPointer) { - on(document, 'pointermove', this._handleFallbackAutoScroll); - } else if (originalEvent.touches) { - on(document, 'touchmove', this._handleFallbackAutoScroll); - } else { - on(document, 'mousemove', this._handleFallbackAutoScroll); - } - } - }, - dragOverCompleted: function dragOverCompleted(_ref2) { - var originalEvent = _ref2.originalEvent; - - // For when bubbling is canceled and using fallback (fallback 'touchmove' always reached) - if (!this.options.dragOverBubble && !originalEvent.rootEl) { - this._handleAutoScroll(originalEvent); - } - }, - drop: function drop() { - if (this.sortable.nativeDraggable) { - off(document, 'dragover', this._handleAutoScroll); - } else { - off(document, 'pointermove', this._handleFallbackAutoScroll); - off(document, 'touchmove', this._handleFallbackAutoScroll); - off(document, 'mousemove', this._handleFallbackAutoScroll); - } - - clearPointerElemChangedInterval(); - clearAutoScrolls(); - cancelThrottle(); - }, - nulling: function nulling() { - touchEvt$1 = scrollRootEl = scrollEl = scrolling = pointerElemChangedInterval = lastAutoScrollX = lastAutoScrollY = null; - autoScrolls.length = 0; - }, - _handleFallbackAutoScroll: function _handleFallbackAutoScroll(evt) { - this._handleAutoScroll(evt, true); - }, - _handleAutoScroll: function _handleAutoScroll(evt, fallback) { - var _this = this; - - var x = (evt.touches ? evt.touches[0] : evt).clientX, - y = (evt.touches ? evt.touches[0] : evt).clientY, - elem = document.elementFromPoint(x, y); - touchEvt$1 = evt; // IE does not seem to have native autoscroll, - // Edge's autoscroll seems too conditional, - // MACOS Safari does not have autoscroll, - // Firefox and Chrome are good - - if (fallback || this.options.forceAutoScrollFallback || Edge || IE11OrLess || Safari) { - autoScroll(evt, this.options, elem, fallback); // Listener for pointer element change - - var ogElemScroller = getParentAutoScrollElement(elem, true); - - if (scrolling && (!pointerElemChangedInterval || x !== lastAutoScrollX || y !== lastAutoScrollY)) { - pointerElemChangedInterval && clearPointerElemChangedInterval(); // Detect for pointer elem change, emulating native DnD behaviour - - pointerElemChangedInterval = setInterval(function () { - var newElem = getParentAutoScrollElement(document.elementFromPoint(x, y), true); - - if (newElem !== ogElemScroller) { - ogElemScroller = newElem; - clearAutoScrolls(); - } - - autoScroll(evt, _this.options, newElem, fallback); - }, 10); - lastAutoScrollX = x; - lastAutoScrollY = y; - } - } else { - // if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll - if (!this.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) { - clearAutoScrolls(); - return; - } - - autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false); - } - } - }; - return _extends(AutoScroll, { - pluginName: 'scroll', - initializeByDefault: true - }); -} - -function clearAutoScrolls() { - autoScrolls.forEach(function (autoScroll) { - clearInterval(autoScroll.pid); - }); - autoScrolls = []; -} - -function clearPointerElemChangedInterval() { - clearInterval(pointerElemChangedInterval); -} - -var autoScroll = throttle(function (evt, options, rootEl, isFallback) { - // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521 - if (!options.scroll) return; - var x = (evt.touches ? evt.touches[0] : evt).clientX, - y = (evt.touches ? evt.touches[0] : evt).clientY, - sens = options.scrollSensitivity, - speed = options.scrollSpeed, - winScroller = getWindowScrollingElement(); - var scrollThisInstance = false, - scrollCustomFn; // New scroll root, set scrollEl - - if (scrollRootEl !== rootEl) { - scrollRootEl = rootEl; - clearAutoScrolls(); - scrollEl = options.scroll; - scrollCustomFn = options.scrollFn; - - if (scrollEl === true) { - scrollEl = getParentAutoScrollElement(rootEl, true); - } - } - - var layersOut = 0; - var currentParent = scrollEl; - - do { - var el = currentParent, - rect = getRect(el), - top = rect.top, - bottom = rect.bottom, - left = rect.left, - right = rect.right, - width = rect.width, - height = rect.height, - canScrollX = void 0, - canScrollY = void 0, - scrollWidth = el.scrollWidth, - scrollHeight = el.scrollHeight, - elCSS = css(el), - scrollPosX = el.scrollLeft, - scrollPosY = el.scrollTop; - - if (el === winScroller) { - canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll' || elCSS.overflowX === 'visible'); - canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll' || elCSS.overflowY === 'visible'); - } else { - canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll'); - canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll'); - } - - var vx = canScrollX && (Math.abs(right - x) <= sens && scrollPosX + width < scrollWidth) - (Math.abs(left - x) <= sens && !!scrollPosX); - var vy = canScrollY && (Math.abs(bottom - y) <= sens && scrollPosY + height < scrollHeight) - (Math.abs(top - y) <= sens && !!scrollPosY); - - if (!autoScrolls[layersOut]) { - for (var i = 0; i <= layersOut; i++) { - if (!autoScrolls[i]) { - autoScrolls[i] = {}; - } - } - } - - if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) { - autoScrolls[layersOut].el = el; - autoScrolls[layersOut].vx = vx; - autoScrolls[layersOut].vy = vy; - clearInterval(autoScrolls[layersOut].pid); - - if (vx != 0 || vy != 0) { - scrollThisInstance = true; - /* jshint loopfunc:true */ - - autoScrolls[layersOut].pid = setInterval(function () { - // emulate drag over during autoscroll (fallback), emulating native DnD behaviour - if (isFallback && this.layer === 0) { - Sortable.active._onTouchMove(touchEvt$1); // To move ghost if it is positioned absolutely - - } - - var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0; - var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0; - - if (typeof scrollCustomFn === 'function') { - if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== 'continue') { - return; - } - } - - scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY); - }.bind({ - layer: layersOut - }), 24); - } - } - - layersOut++; - } while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false))); - - scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not -}, 30); - -var drop = function drop(_ref) { - var originalEvent = _ref.originalEvent, - putSortable = _ref.putSortable, - dragEl = _ref.dragEl, - activeSortable = _ref.activeSortable, - dispatchSortableEvent = _ref.dispatchSortableEvent, - hideGhostForTarget = _ref.hideGhostForTarget, - unhideGhostForTarget = _ref.unhideGhostForTarget; - if (!originalEvent) return; - var toSortable = putSortable || activeSortable; - hideGhostForTarget(); - var touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent; - var target = document.elementFromPoint(touch.clientX, touch.clientY); - unhideGhostForTarget(); - - if (toSortable && !toSortable.el.contains(target)) { - dispatchSortableEvent('spill'); - this.onSpill({ - dragEl: dragEl, - putSortable: putSortable - }); - } -}; - -function Revert() {} - -Revert.prototype = { - startIndex: null, - dragStart: function dragStart(_ref2) { - var oldDraggableIndex = _ref2.oldDraggableIndex; - this.startIndex = oldDraggableIndex; - }, - onSpill: function onSpill(_ref3) { - var dragEl = _ref3.dragEl, - putSortable = _ref3.putSortable; - this.sortable.captureAnimationState(); - - if (putSortable) { - putSortable.captureAnimationState(); - } - - var nextSibling = getChild(this.sortable.el, this.startIndex, this.options); - - if (nextSibling) { - this.sortable.el.insertBefore(dragEl, nextSibling); - } else { - this.sortable.el.appendChild(dragEl); - } - - this.sortable.animateAll(); - - if (putSortable) { - putSortable.animateAll(); - } - }, - drop: drop -}; - -_extends(Revert, { - pluginName: 'revertOnSpill' -}); - -function Remove() {} - -Remove.prototype = { - onSpill: function onSpill(_ref4) { - var dragEl = _ref4.dragEl, - putSortable = _ref4.putSortable; - var parentSortable = putSortable || this.sortable; - parentSortable.captureAnimationState(); - dragEl.parentNode && dragEl.parentNode.removeChild(dragEl); - parentSortable.animateAll(); - }, - drop: drop -}; - -_extends(Remove, { - pluginName: 'removeOnSpill' -}); - -Sortable.mount(new AutoScrollPlugin()); -Sortable.mount(Remove, Revert); - -var RegexEvent; -(function (RegexEvent) { - (function (ParsonsInputAction) { - ParsonsInputAction["ADD"] = "add"; - ParsonsInputAction["MOVE"] = "move"; - ParsonsInputAction["REMOVE"] = "remove"; - })(RegexEvent.ParsonsInputAction || (RegexEvent.ParsonsInputAction = {})); - (function (RegexCompilationStatus) { - RegexCompilationStatus["ERROR"] = "error"; - RegexCompilationStatus["SUCCESS"] = "success"; - })(RegexEvent.RegexCompilationStatus || (RegexEvent.RegexCompilationStatus = {})); - (function (MatchTriggerType) { - MatchTriggerType["MANUAL"] = "manual"; - MatchTriggerType["AUTO"] = "auto"; - })(RegexEvent.MatchTriggerType || (RegexEvent.MatchTriggerType = {})); - (function (PageStatus) { - PageStatus["FOCUS"] = "focus"; - PageStatus["VISIBILITY"] = "visibility"; - })(RegexEvent.PageStatus || (RegexEvent.PageStatus = {})); -})(RegexEvent || (RegexEvent = {})); - -var deepFreezeEs6 = {exports: {}}; - -function deepFreeze(obj) { - if (obj instanceof Map) { - obj.clear = obj.delete = obj.set = function () { - throw new Error('map is read-only'); - }; - } else if (obj instanceof Set) { - obj.add = obj.clear = obj.delete = function () { - throw new Error('set is read-only'); - }; - } - - // Freeze self - Object.freeze(obj); - - Object.getOwnPropertyNames(obj).forEach(function (name) { - var prop = obj[name]; - - // Freeze prop if it is an object - if (typeof prop == 'object' && !Object.isFrozen(prop)) { - deepFreeze(prop); - } - }); - - return obj; -} - -deepFreezeEs6.exports = deepFreeze; -deepFreezeEs6.exports.default = deepFreeze; - -var deepFreeze$1 = deepFreezeEs6.exports; - -/** @typedef {import('highlight.js').CallbackResponse} CallbackResponse */ -/** @typedef {import('highlight.js').CompiledMode} CompiledMode */ -/** @implements CallbackResponse */ - -class Response { - /** - * @param {CompiledMode} mode - */ - constructor(mode) { - // eslint-disable-next-line no-undefined - if (mode.data === undefined) mode.data = {}; - - this.data = mode.data; - this.isMatchIgnored = false; - } - - ignoreMatch() { - this.isMatchIgnored = true; - } -} - -/** - * @param {string} value - * @returns {string} - */ -function escapeHTML(value) { - return value - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} - -/** - * performs a shallow merge of multiple objects into one - * - * @template T - * @param {T} original - * @param {Record[]} objects - * @returns {T} a single new object - */ -function inherit$1(original, ...objects) { - /** @type Record */ - const result = Object.create(null); - - for (const key in original) { - result[key] = original[key]; - } - objects.forEach(function(obj) { - for (const key in obj) { - result[key] = obj[key]; - } - }); - return /** @type {T} */ (result); -} - -/** - * @typedef {object} Renderer - * @property {(text: string) => void} addText - * @property {(node: Node) => void} openNode - * @property {(node: Node) => void} closeNode - * @property {() => string} value - */ - -/** @typedef {{kind?: string, sublanguage?: boolean}} Node */ -/** @typedef {{walk: (r: Renderer) => void}} Tree */ -/** */ - -const SPAN_CLOSE = ''; - -/** - * Determines if a node needs to be wrapped in - * - * @param {Node} node */ -const emitsWrappingTags = (node) => { - return !!node.kind; -}; - -/** - * - * @param {string} name - * @param {{prefix:string}} options - */ -const expandScopeName = (name, { prefix }) => { - if (name.includes(".")) { - const pieces = name.split("."); - return [ - `${prefix}${pieces.shift()}`, - ...(pieces.map((x, i) => `${x}${"_".repeat(i + 1)}`)) - ].join(" "); - } - return `${prefix}${name}`; -}; - -/** @type {Renderer} */ -class HTMLRenderer { - /** - * Creates a new HTMLRenderer - * - * @param {Tree} parseTree - the parse tree (must support `walk` API) - * @param {{classPrefix: string}} options - */ - constructor(parseTree, options) { - this.buffer = ""; - this.classPrefix = options.classPrefix; - parseTree.walk(this); - } - - /** - * Adds texts to the output stream - * - * @param {string} text */ - addText(text) { - this.buffer += escapeHTML(text); - } - - /** - * Adds a node open to the output stream (if needed) - * - * @param {Node} node */ - openNode(node) { - if (!emitsWrappingTags(node)) return; - - let scope = node.kind; - if (node.sublanguage) { - scope = `language-${scope}`; - } else { - scope = expandScopeName(scope, { prefix: this.classPrefix }); - } - this.span(scope); - } - - /** - * Adds a node close to the output stream (if needed) - * - * @param {Node} node */ - closeNode(node) { - if (!emitsWrappingTags(node)) return; - - this.buffer += SPAN_CLOSE; - } - - /** - * returns the accumulated buffer - */ - value() { - return this.buffer; - } - - // helpers - - /** - * Builds a span element - * - * @param {string} className */ - span(className) { - this.buffer += ``; - } -} - -/** @typedef {{kind?: string, sublanguage?: boolean, children: Node[]} | string} Node */ -/** @typedef {{kind?: string, sublanguage?: boolean, children: Node[]} } DataNode */ -/** @typedef {import('highlight.js').Emitter} Emitter */ -/** */ - -class TokenTree { - constructor() { - /** @type DataNode */ - this.rootNode = { children: [] }; - this.stack = [this.rootNode]; - } - - get top() { - return this.stack[this.stack.length - 1]; - } - - get root() { return this.rootNode; } - - /** @param {Node} node */ - add(node) { - this.top.children.push(node); - } - - /** @param {string} kind */ - openNode(kind) { - /** @type Node */ - const node = { kind, children: [] }; - this.add(node); - this.stack.push(node); - } - - closeNode() { - if (this.stack.length > 1) { - return this.stack.pop(); - } - // eslint-disable-next-line no-undefined - return undefined; - } - - closeAllNodes() { - while (this.closeNode()); - } - - toJSON() { - return JSON.stringify(this.rootNode, null, 4); - } - - /** - * @typedef { import("./html_renderer").Renderer } Renderer - * @param {Renderer} builder - */ - walk(builder) { - // this does not - return this.constructor._walk(builder, this.rootNode); - // this works - // return TokenTree._walk(builder, this.rootNode); - } - - /** - * @param {Renderer} builder - * @param {Node} node - */ - static _walk(builder, node) { - if (typeof node === "string") { - builder.addText(node); - } else if (node.children) { - builder.openNode(node); - node.children.forEach((child) => this._walk(builder, child)); - builder.closeNode(node); - } - return builder; - } - - /** - * @param {Node} node - */ - static _collapse(node) { - if (typeof node === "string") return; - if (!node.children) return; - - if (node.children.every(el => typeof el === "string")) { - // node.text = node.children.join(""); - // delete node.children; - node.children = [node.children.join("")]; - } else { - node.children.forEach((child) => { - TokenTree._collapse(child); - }); - } - } -} - -/** - Currently this is all private API, but this is the minimal API necessary - that an Emitter must implement to fully support the parser. - - Minimal interface: - - - addKeyword(text, kind) - - addText(text) - - addSublanguage(emitter, subLanguageName) - - finalize() - - openNode(kind) - - closeNode() - - closeAllNodes() - - toHTML() - -*/ - -/** - * @implements {Emitter} - */ -class TokenTreeEmitter extends TokenTree { - /** - * @param {*} options - */ - constructor(options) { - super(); - this.options = options; - } - - /** - * @param {string} text - * @param {string} kind - */ - addKeyword(text, kind) { - if (text === "") { return; } - - this.openNode(kind); - this.addText(text); - this.closeNode(); - } - - /** - * @param {string} text - */ - addText(text) { - if (text === "") { return; } - - this.add(text); - } - - /** - * @param {Emitter & {root: DataNode}} emitter - * @param {string} name - */ - addSublanguage(emitter, name) { - /** @type DataNode */ - const node = emitter.root; - node.kind = name; - node.sublanguage = true; - this.add(node); - } - - toHTML() { - const renderer = new HTMLRenderer(this, this.options); - return renderer.value(); - } - - finalize() { - return true; - } -} - -/** - * @param {string} value - * @returns {RegExp} - * */ - -/** - * @param {RegExp | string } re - * @returns {string} - */ -function source(re) { - if (!re) return null; - if (typeof re === "string") return re; - - return re.source; -} - -/** - * @param {RegExp | string } re - * @returns {string} - */ -function lookahead(re) { - return concat('(?=', re, ')'); -} - -/** - * @param {RegExp | string } re - * @returns {string} - */ -function anyNumberOfTimes(re) { - return concat('(?:', re, ')*'); -} - -/** - * @param {RegExp | string } re - * @returns {string} - */ -function optional(re) { - return concat('(?:', re, ')?'); -} - -/** - * @param {...(RegExp | string) } args - * @returns {string} - */ -function concat(...args) { - const joined = args.map((x) => source(x)).join(""); - return joined; -} - -/** - * @param { Array } args - * @returns {object} - */ -function stripOptionsFromArgs(args) { - const opts = args[args.length - 1]; - - if (typeof opts === 'object' && opts.constructor === Object) { - args.splice(args.length - 1, 1); - return opts; - } else { - return {}; - } -} - -/** @typedef { {capture?: boolean} } RegexEitherOptions */ - -/** - * Any of the passed expresssions may match - * - * Creates a huge this | this | that | that match - * @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args - * @returns {string} - */ -function either(...args) { - /** @type { object & {capture?: boolean} } */ - const opts = stripOptionsFromArgs(args); - const joined = '(' - + (opts.capture ? "" : "?:") - + args.map((x) => source(x)).join("|") + ")"; - return joined; -} - -/** - * @param {RegExp | string} re - * @returns {number} - */ -function countMatchGroups(re) { - return (new RegExp(re.toString() + '|')).exec('').length - 1; -} - -/** - * Does lexeme start with a regular expression match at the beginning - * @param {RegExp} re - * @param {string} lexeme - */ -function startsWith(re, lexeme) { - const match = re && re.exec(lexeme); - return match && match.index === 0; -} - -// BACKREF_RE matches an open parenthesis or backreference. To avoid -// an incorrect parse, it additionally matches the following: -// - [...] elements, where the meaning of parentheses and escapes change -// - other escape sequences, so we do not misparse escape sequences as -// interesting elements -// - non-matching or lookahead parentheses, which do not capture. These -// follow the '(' with a '?'. -const BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./; - -// **INTERNAL** Not intended for outside usage -// join logically computes regexps.join(separator), but fixes the -// backreferences so they continue to match. -// it also places each individual regular expression into it's own -// match group, keeping track of the sequencing of those match groups -// is currently an exercise for the caller. :-) -/** - * @param {(string | RegExp)[]} regexps - * @param {{joinWith: string}} opts - * @returns {string} - */ -function _rewriteBackreferences(regexps, { joinWith }) { - let numCaptures = 0; - - return regexps.map((regex) => { - numCaptures += 1; - const offset = numCaptures; - let re = source(regex); - let out = ''; - - while (re.length > 0) { - const match = BACKREF_RE.exec(re); - if (!match) { - out += re; - break; - } - out += re.substring(0, match.index); - re = re.substring(match.index + match[0].length); - if (match[0][0] === '\\' && match[1]) { - // Adjust the backreference. - out += '\\' + String(Number(match[1]) + offset); - } else { - out += match[0]; - if (match[0] === '(') { - numCaptures++; - } - } - } - return out; - }).map(re => `(${re})`).join(joinWith); -} - -/** @typedef {import('highlight.js').Mode} Mode */ -/** @typedef {import('highlight.js').ModeCallback} ModeCallback */ - -// Common regexps -const MATCH_NOTHING_RE = /\b\B/; -const IDENT_RE$1 = '[a-zA-Z]\\w*'; -const UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*'; -const NUMBER_RE = '\\b\\d+(\\.\\d+)?'; -const C_NUMBER_RE = '(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float -const BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b... -const RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~'; - -/** -* @param { Partial & {binary?: string | RegExp} } opts -*/ -const SHEBANG = (opts = {}) => { - const beginShebang = /^#![ ]*\//; - if (opts.binary) { - opts.begin = concat( - beginShebang, - /.*\b/, - opts.binary, - /\b.*/); - } - return inherit$1({ - scope: 'meta', - begin: beginShebang, - end: /$/, - relevance: 0, - /** @type {ModeCallback} */ - "on:begin": (m, resp) => { - if (m.index !== 0) resp.ignoreMatch(); - } - }, opts); -}; - -// Common modes -const BACKSLASH_ESCAPE = { - begin: '\\\\[\\s\\S]', relevance: 0 -}; -const APOS_STRING_MODE = { - scope: 'string', - begin: '\'', - end: '\'', - illegal: '\\n', - contains: [BACKSLASH_ESCAPE] -}; -const QUOTE_STRING_MODE = { - scope: 'string', - begin: '"', - end: '"', - illegal: '\\n', - contains: [BACKSLASH_ESCAPE] -}; -const PHRASAL_WORDS_MODE = { - begin: /\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ -}; -/** - * Creates a comment mode - * - * @param {string | RegExp} begin - * @param {string | RegExp} end - * @param {Mode | {}} [modeOptions] - * @returns {Partial} - */ -const COMMENT = function(begin, end, modeOptions = {}) { - const mode = inherit$1( - { - scope: 'comment', - begin, - end, - contains: [] - }, - modeOptions - ); - mode.contains.push({ - scope: 'doctag', - // hack to avoid the space from being included. the space is necessary to - // match here to prevent the plain text rule below from gobbling up doctags - begin: '[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)', - end: /(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/, - excludeBegin: true, - relevance: 0 - }); - const ENGLISH_WORD = either( - // list of common 1 and 2 letter words in English - "I", - "a", - "is", - "so", - "us", - "to", - "at", - "if", - "in", - "it", - "on", - // note: this is not an exhaustive list of contractions, just popular ones - /[A-Za-z]+['](d|ve|re|ll|t|s|n)/, // contractions - can't we'd they're let's, etc - /[A-Za-z]+[-][a-z]+/, // `no-way`, etc. - /[A-Za-z][a-z]{2,}/ // allow capitalized words at beginning of sentences - ); - // looking like plain text, more likely to be a comment - mode.contains.push( - { - // TODO: how to include ", (, ) without breaking grammars that use these for - // comment delimiters? - // begin: /[ ]+([()"]?([A-Za-z'-]{3,}|is|a|I|so|us|[tT][oO]|at|if|in|it|on)[.]?[()":]?([.][ ]|[ ]|\))){3}/ - // --- - - // this tries to find sequences of 3 english words in a row (without any - // "programming" type syntax) this gives us a strong signal that we've - // TRULY found a comment - vs perhaps scanning with the wrong language. - // It's possible to find something that LOOKS like the start of the - // comment - but then if there is no readable text - good chance it is a - // false match and not a comment. - // - // for a visual example please see: - // https://github.com/highlightjs/highlight.js/issues/2827 - - begin: concat( - /[ ]+/, // necessary to prevent us gobbling up doctags like /* @author Bob Mcgill */ - '(', - ENGLISH_WORD, - /[.]?[:]?([.][ ]|[ ])/, - '){3}') // look for 3 words in a row - } - ); - return mode; -}; -const C_LINE_COMMENT_MODE = COMMENT('//', '$'); -const C_BLOCK_COMMENT_MODE = COMMENT('/\\*', '\\*/'); -const HASH_COMMENT_MODE = COMMENT('#', '$'); -const NUMBER_MODE = { - scope: 'number', - begin: NUMBER_RE, - relevance: 0 -}; -const C_NUMBER_MODE = { - scope: 'number', - begin: C_NUMBER_RE, - relevance: 0 -}; -const BINARY_NUMBER_MODE = { - scope: 'number', - begin: BINARY_NUMBER_RE, - relevance: 0 -}; -const REGEXP_MODE = { - // this outer rule makes sure we actually have a WHOLE regex and not simply - // an expression such as: - // - // 3 / something - // - // (which will then blow up when regex's `illegal` sees the newline) - begin: /(?=\/[^/\n]*\/)/, - contains: [{ - scope: 'regexp', - begin: /\//, - end: /\/[gimuy]*/, - illegal: /\n/, - contains: [ - BACKSLASH_ESCAPE, - { - begin: /\[/, - end: /\]/, - relevance: 0, - contains: [BACKSLASH_ESCAPE] - } - ] - }] -}; -const TITLE_MODE = { - scope: 'title', - begin: IDENT_RE$1, - relevance: 0 -}; -const UNDERSCORE_TITLE_MODE = { - scope: 'title', - begin: UNDERSCORE_IDENT_RE, - relevance: 0 -}; -const METHOD_GUARD = { - // excludes method names from keyword processing - begin: '\\.\\s*' + UNDERSCORE_IDENT_RE, - relevance: 0 -}; - -/** - * Adds end same as begin mechanics to a mode - * - * Your mode must include at least a single () match group as that first match - * group is what is used for comparison - * @param {Partial} mode - */ -const END_SAME_AS_BEGIN = function(mode) { - return Object.assign(mode, - { - /** @type {ModeCallback} */ - 'on:begin': (m, resp) => { resp.data._beginMatch = m[1]; }, - /** @type {ModeCallback} */ - 'on:end': (m, resp) => { if (resp.data._beginMatch !== m[1]) resp.ignoreMatch(); } - }); -}; - -var MODES = /*#__PURE__*/Object.freeze({ - __proto__: null, - MATCH_NOTHING_RE: MATCH_NOTHING_RE, - IDENT_RE: IDENT_RE$1, - UNDERSCORE_IDENT_RE: UNDERSCORE_IDENT_RE, - NUMBER_RE: NUMBER_RE, - C_NUMBER_RE: C_NUMBER_RE, - BINARY_NUMBER_RE: BINARY_NUMBER_RE, - RE_STARTERS_RE: RE_STARTERS_RE, - SHEBANG: SHEBANG, - BACKSLASH_ESCAPE: BACKSLASH_ESCAPE, - APOS_STRING_MODE: APOS_STRING_MODE, - QUOTE_STRING_MODE: QUOTE_STRING_MODE, - PHRASAL_WORDS_MODE: PHRASAL_WORDS_MODE, - COMMENT: COMMENT, - C_LINE_COMMENT_MODE: C_LINE_COMMENT_MODE, - C_BLOCK_COMMENT_MODE: C_BLOCK_COMMENT_MODE, - HASH_COMMENT_MODE: HASH_COMMENT_MODE, - NUMBER_MODE: NUMBER_MODE, - C_NUMBER_MODE: C_NUMBER_MODE, - BINARY_NUMBER_MODE: BINARY_NUMBER_MODE, - REGEXP_MODE: REGEXP_MODE, - TITLE_MODE: TITLE_MODE, - UNDERSCORE_TITLE_MODE: UNDERSCORE_TITLE_MODE, - METHOD_GUARD: METHOD_GUARD, - END_SAME_AS_BEGIN: END_SAME_AS_BEGIN -}); - -/** -@typedef {import('highlight.js').CallbackResponse} CallbackResponse -@typedef {import('highlight.js').CompilerExt} CompilerExt -*/ - -// Grammar extensions / plugins -// See: https://github.com/highlightjs/highlight.js/issues/2833 - -// Grammar extensions allow "syntactic sugar" to be added to the grammar modes -// without requiring any underlying changes to the compiler internals. - -// `compileMatch` being the perfect small example of now allowing a grammar -// author to write `match` when they desire to match a single expression rather -// than being forced to use `begin`. The extension then just moves `match` into -// `begin` when it runs. Ie, no features have been added, but we've just made -// the experience of writing (and reading grammars) a little bit nicer. - -// ------ - -// TODO: We need negative look-behind support to do this properly -/** - * Skip a match if it has a preceding dot - * - * This is used for `beginKeywords` to prevent matching expressions such as - * `bob.keyword.do()`. The mode compiler automatically wires this up as a - * special _internal_ 'on:begin' callback for modes with `beginKeywords` - * @param {RegExpMatchArray} match - * @param {CallbackResponse} response - */ -function skipIfHasPrecedingDot(match, response) { - const before = match.input[match.index - 1]; - if (before === ".") { - response.ignoreMatch(); - } -} - -/** - * - * @type {CompilerExt} - */ -function scopeClassName(mode, _parent) { - // eslint-disable-next-line no-undefined - if (mode.className !== undefined) { - mode.scope = mode.className; - delete mode.className; - } -} - -/** - * `beginKeywords` syntactic sugar - * @type {CompilerExt} - */ -function beginKeywords(mode, parent) { - if (!parent) return; - if (!mode.beginKeywords) return; - - // for languages with keywords that include non-word characters checking for - // a word boundary is not sufficient, so instead we check for a word boundary - // or whitespace - this does no harm in any case since our keyword engine - // doesn't allow spaces in keywords anyways and we still check for the boundary - // first - mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\.)(?=\\b|\\s)'; - mode.__beforeBegin = skipIfHasPrecedingDot; - mode.keywords = mode.keywords || mode.beginKeywords; - delete mode.beginKeywords; - - // prevents double relevance, the keywords themselves provide - // relevance, the mode doesn't need to double it - // eslint-disable-next-line no-undefined - if (mode.relevance === undefined) mode.relevance = 0; -} - -/** - * Allow `illegal` to contain an array of illegal values - * @type {CompilerExt} - */ -function compileIllegal(mode, _parent) { - if (!Array.isArray(mode.illegal)) return; - - mode.illegal = either(...mode.illegal); -} - -/** - * `match` to match a single expression for readability - * @type {CompilerExt} - */ -function compileMatch(mode, _parent) { - if (!mode.match) return; - if (mode.begin || mode.end) throw new Error("begin & end are not supported with match"); - - mode.begin = mode.match; - delete mode.match; -} - -/** - * provides the default 1 relevance to all modes - * @type {CompilerExt} - */ -function compileRelevance(mode, _parent) { - // eslint-disable-next-line no-undefined - if (mode.relevance === undefined) mode.relevance = 1; -} - -// allow beforeMatch to act as a "qualifier" for the match -// the full match begin must be [beforeMatch][begin] -const beforeMatchExt = (mode, parent) => { - if (!mode.beforeMatch) return; - // starts conflicts with endsParent which we need to make sure the child - // rule is not matched multiple times - if (mode.starts) throw new Error("beforeMatch cannot be used with starts"); - - const originalMode = Object.assign({}, mode); - Object.keys(mode).forEach((key) => { delete mode[key]; }); - - mode.keywords = originalMode.keywords; - mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin)); - mode.starts = { - relevance: 0, - contains: [ - Object.assign(originalMode, { endsParent: true }) - ] - }; - mode.relevance = 0; - - delete originalMode.beforeMatch; -}; - -// keywords that should have no default relevance value -const COMMON_KEYWORDS = [ - 'of', - 'and', - 'for', - 'in', - 'not', - 'or', - 'if', - 'then', - 'parent', // common variable name - 'list', // common variable name - 'value' // common variable name -]; - -const DEFAULT_KEYWORD_SCOPE = "keyword"; - -/** - * Given raw keywords from a language definition, compile them. - * - * @param {string | Record | Array} rawKeywords - * @param {boolean} caseInsensitive - */ -function compileKeywords(rawKeywords, caseInsensitive, scopeName = DEFAULT_KEYWORD_SCOPE) { - /** @type KeywordDict */ - const compiledKeywords = Object.create(null); - - // input can be a string of keywords, an array of keywords, or a object with - // named keys representing scopeName (which can then point to a string or array) - if (typeof rawKeywords === 'string') { - compileList(scopeName, rawKeywords.split(" ")); - } else if (Array.isArray(rawKeywords)) { - compileList(scopeName, rawKeywords); - } else { - Object.keys(rawKeywords).forEach(function(scopeName) { - // collapse all our objects back into the parent object - Object.assign( - compiledKeywords, - compileKeywords(rawKeywords[scopeName], caseInsensitive, scopeName) - ); - }); - } - return compiledKeywords; - - // --- - - /** - * Compiles an individual list of keywords - * - * Ex: "for if when while|5" - * - * @param {string} scopeName - * @param {Array} keywordList - */ - function compileList(scopeName, keywordList) { - if (caseInsensitive) { - keywordList = keywordList.map(x => x.toLowerCase()); - } - keywordList.forEach(function(keyword) { - const pair = keyword.split('|'); - compiledKeywords[pair[0]] = [scopeName, scoreForKeyword(pair[0], pair[1])]; - }); - } -} - -/** - * Returns the proper score for a given keyword - * - * Also takes into account comment keywords, which will be scored 0 UNLESS - * another score has been manually assigned. - * @param {string} keyword - * @param {string} [providedScore] - */ -function scoreForKeyword(keyword, providedScore) { - // manual scores always win over common keywords - // so you can force a score of 1 if you really insist - if (providedScore) { - return Number(providedScore); - } - - return commonKeyword(keyword) ? 0 : 1; -} - -/** - * Determines if a given keyword is common or not - * - * @param {string} keyword */ -function commonKeyword(keyword) { - return COMMON_KEYWORDS.includes(keyword.toLowerCase()); -} - -/* - -For the reasoning behind this please see: -https://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419 - -*/ - -/** - * @type {Record} - */ -const seenDeprecations = {}; - -/** - * @param {string} message - */ -const error = (message) => { - console.error(message); -}; - -/** - * @param {string} message - * @param {any} args - */ -const warn = (message, ...args) => { - console.log(`WARN: ${message}`, ...args); -}; - -/** - * @param {string} version - * @param {string} message - */ -const deprecated = (version, message) => { - if (seenDeprecations[`${version}/${message}`]) return; - - console.log(`Deprecated as of ${version}. ${message}`); - seenDeprecations[`${version}/${message}`] = true; -}; - -/* eslint-disable no-throw-literal */ - -/** -@typedef {import('highlight.js').CompiledMode} CompiledMode -*/ - -const MultiClassError = new Error(); - -/** - * Renumbers labeled scope names to account for additional inner match - * groups that otherwise would break everything. - * - * Lets say we 3 match scopes: - * - * { 1 => ..., 2 => ..., 3 => ... } - * - * So what we need is a clean match like this: - * - * (a)(b)(c) => [ "a", "b", "c" ] - * - * But this falls apart with inner match groups: - * - * (a)(((b)))(c) => ["a", "b", "b", "b", "c" ] - * - * Our scopes are now "out of alignment" and we're repeating `b` 3 times. - * What needs to happen is the numbers are remapped: - * - * { 1 => ..., 2 => ..., 5 => ... } - * - * We also need to know that the ONLY groups that should be output - * are 1, 2, and 5. This function handles this behavior. - * - * @param {CompiledMode} mode - * @param {Array} regexes - * @param {{key: "beginScope"|"endScope"}} opts - */ -function remapScopeNames(mode, regexes, { key }) { - let offset = 0; - const scopeNames = mode[key]; - /** @type Record */ - const emit = {}; - /** @type Record */ - const positions = {}; - - for (let i = 1; i <= regexes.length; i++) { - positions[i + offset] = scopeNames[i]; - emit[i + offset] = true; - offset += countMatchGroups(regexes[i - 1]); - } - // we use _emit to keep track of which match groups are "top-level" to avoid double - // output from inside match groups - mode[key] = positions; - mode[key]._emit = emit; - mode[key]._multi = true; -} - -/** - * @param {CompiledMode} mode - */ -function beginMultiClass(mode) { - if (!Array.isArray(mode.begin)) return; - - if (mode.skip || mode.excludeBegin || mode.returnBegin) { - error("skip, excludeBegin, returnBegin not compatible with beginScope: {}"); - throw MultiClassError; - } - - if (typeof mode.beginScope !== "object" || mode.beginScope === null) { - error("beginScope must be object"); - throw MultiClassError; - } - - remapScopeNames(mode, mode.begin, { key: "beginScope" }); - mode.begin = _rewriteBackreferences(mode.begin, { joinWith: "" }); -} - -/** - * @param {CompiledMode} mode - */ -function endMultiClass(mode) { - if (!Array.isArray(mode.end)) return; - - if (mode.skip || mode.excludeEnd || mode.returnEnd) { - error("skip, excludeEnd, returnEnd not compatible with endScope: {}"); - throw MultiClassError; - } - - if (typeof mode.endScope !== "object" || mode.endScope === null) { - error("endScope must be object"); - throw MultiClassError; - } - - remapScopeNames(mode, mode.end, { key: "endScope" }); - mode.end = _rewriteBackreferences(mode.end, { joinWith: "" }); -} - -/** - * this exists only to allow `scope: {}` to be used beside `match:` - * Otherwise `beginScope` would necessary and that would look weird - - { - match: [ /def/, /\w+/ ] - scope: { 1: "keyword" , 2: "title" } - } - - * @param {CompiledMode} mode - */ -function scopeSugar(mode) { - if (mode.scope && typeof mode.scope === "object" && mode.scope !== null) { - mode.beginScope = mode.scope; - delete mode.scope; - } -} - -/** - * @param {CompiledMode} mode - */ -function MultiClass(mode) { - scopeSugar(mode); - - if (typeof mode.beginScope === "string") { - mode.beginScope = { _wrap: mode.beginScope }; - } - if (typeof mode.endScope === "string") { - mode.endScope = { _wrap: mode.endScope }; - } - - beginMultiClass(mode); - endMultiClass(mode); -} - -/** -@typedef {import('highlight.js').Mode} Mode -@typedef {import('highlight.js').CompiledMode} CompiledMode -@typedef {import('highlight.js').Language} Language -@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin -@typedef {import('highlight.js').CompiledLanguage} CompiledLanguage -*/ - -// compilation - -/** - * Compiles a language definition result - * - * Given the raw result of a language definition (Language), compiles this so - * that it is ready for highlighting code. - * @param {Language} language - * @returns {CompiledLanguage} - */ -function compileLanguage(language) { - /** - * Builds a regex with the case sensitivity of the current language - * - * @param {RegExp | string} value - * @param {boolean} [global] - */ - function langRe(value, global) { - return new RegExp( - source(value), - 'm' - + (language.case_insensitive ? 'i' : '') - + (language.unicodeRegex ? 'u' : '') - + (global ? 'g' : '') - ); - } - - /** - Stores multiple regular expressions and allows you to quickly search for - them all in a string simultaneously - returning the first match. It does - this by creating a huge (a|b|c) regex - each individual item wrapped with () - and joined by `|` - using match groups to track position. When a match is - found checking which position in the array has content allows us to figure - out which of the original regexes / match groups triggered the match. - - The match object itself (the result of `Regex.exec`) is returned but also - enhanced by merging in any meta-data that was registered with the regex. - This is how we keep track of which mode matched, and what type of rule - (`illegal`, `begin`, end, etc). - */ - class MultiRegex { - constructor() { - this.matchIndexes = {}; - // @ts-ignore - this.regexes = []; - this.matchAt = 1; - this.position = 0; - } - - // @ts-ignore - addRule(re, opts) { - opts.position = this.position++; - // @ts-ignore - this.matchIndexes[this.matchAt] = opts; - this.regexes.push([opts, re]); - this.matchAt += countMatchGroups(re) + 1; - } - - compile() { - if (this.regexes.length === 0) { - // avoids the need to check length every time exec is called - // @ts-ignore - this.exec = () => null; - } - const terminators = this.regexes.map(el => el[1]); - this.matcherRe = langRe(_rewriteBackreferences(terminators, { joinWith: '|' }), true); - this.lastIndex = 0; - } - - /** @param {string} s */ - exec(s) { - this.matcherRe.lastIndex = this.lastIndex; - const match = this.matcherRe.exec(s); - if (!match) { return null; } - - // eslint-disable-next-line no-undefined - const i = match.findIndex((el, i) => i > 0 && el !== undefined); - // @ts-ignore - const matchData = this.matchIndexes[i]; - // trim off any earlier non-relevant match groups (ie, the other regex - // match groups that make up the multi-matcher) - match.splice(0, i); - - return Object.assign(match, matchData); - } - } - - /* - Created to solve the key deficiently with MultiRegex - there is no way to - test for multiple matches at a single location. Why would we need to do - that? In the future a more dynamic engine will allow certain matches to be - ignored. An example: if we matched say the 3rd regex in a large group but - decided to ignore it - we'd need to started testing again at the 4th - regex... but MultiRegex itself gives us no real way to do that. - - So what this class creates MultiRegexs on the fly for whatever search - position they are needed. - - NOTE: These additional MultiRegex objects are created dynamically. For most - grammars most of the time we will never actually need anything more than the - first MultiRegex - so this shouldn't have too much overhead. - - Say this is our search group, and we match regex3, but wish to ignore it. - - regex1 | regex2 | regex3 | regex4 | regex5 ' ie, startAt = 0 - - What we need is a new MultiRegex that only includes the remaining - possibilities: - - regex4 | regex5 ' ie, startAt = 3 - - This class wraps all that complexity up in a simple API... `startAt` decides - where in the array of expressions to start doing the matching. It - auto-increments, so if a match is found at position 2, then startAt will be - set to 3. If the end is reached startAt will return to 0. - - MOST of the time the parser will be setting startAt manually to 0. - */ - class ResumableMultiRegex { - constructor() { - // @ts-ignore - this.rules = []; - // @ts-ignore - this.multiRegexes = []; - this.count = 0; - - this.lastIndex = 0; - this.regexIndex = 0; - } - - // @ts-ignore - getMatcher(index) { - if (this.multiRegexes[index]) return this.multiRegexes[index]; - - const matcher = new MultiRegex(); - this.rules.slice(index).forEach(([re, opts]) => matcher.addRule(re, opts)); - matcher.compile(); - this.multiRegexes[index] = matcher; - return matcher; - } - - resumingScanAtSamePosition() { - return this.regexIndex !== 0; - } - - considerAll() { - this.regexIndex = 0; - } - - // @ts-ignore - addRule(re, opts) { - this.rules.push([re, opts]); - if (opts.type === "begin") this.count++; - } - - /** @param {string} s */ - exec(s) { - const m = this.getMatcher(this.regexIndex); - m.lastIndex = this.lastIndex; - let result = m.exec(s); - - // The following is because we have no easy way to say "resume scanning at the - // existing position but also skip the current rule ONLY". What happens is - // all prior rules are also skipped which can result in matching the wrong - // thing. Example of matching "booger": - - // our matcher is [string, "booger", number] - // - // ....booger.... - - // if "booger" is ignored then we'd really need a regex to scan from the - // SAME position for only: [string, number] but ignoring "booger" (if it - // was the first match), a simple resume would scan ahead who knows how - // far looking only for "number", ignoring potential string matches (or - // future "booger" matches that might be valid.) - - // So what we do: We execute two matchers, one resuming at the same - // position, but the second full matcher starting at the position after: - - // /--- resume first regex match here (for [number]) - // |/---- full match here for [string, "booger", number] - // vv - // ....booger.... - - // Which ever results in a match first is then used. So this 3-4 step - // process essentially allows us to say "match at this position, excluding - // a prior rule that was ignored". - // - // 1. Match "booger" first, ignore. Also proves that [string] does non match. - // 2. Resume matching for [number] - // 3. Match at index + 1 for [string, "booger", number] - // 4. If #2 and #3 result in matches, which came first? - if (this.resumingScanAtSamePosition()) { - if (result && result.index === this.lastIndex) ; else { // use the second matcher result - const m2 = this.getMatcher(0); - m2.lastIndex = this.lastIndex + 1; - result = m2.exec(s); - } - } - - if (result) { - this.regexIndex += result.position + 1; - if (this.regexIndex === this.count) { - // wrap-around to considering all matches again - this.considerAll(); - } - } - - return result; - } - } - - /** - * Given a mode, builds a huge ResumableMultiRegex that can be used to walk - * the content and find matches. - * - * @param {CompiledMode} mode - * @returns {ResumableMultiRegex} - */ - function buildModeRegex(mode) { - const mm = new ResumableMultiRegex(); - - mode.contains.forEach(term => mm.addRule(term.begin, { rule: term, type: "begin" })); - - if (mode.terminatorEnd) { - mm.addRule(mode.terminatorEnd, { type: "end" }); - } - if (mode.illegal) { - mm.addRule(mode.illegal, { type: "illegal" }); - } - - return mm; - } - - /** skip vs abort vs ignore - * - * @skip - The mode is still entered and exited normally (and contains rules apply), - * but all content is held and added to the parent buffer rather than being - * output when the mode ends. Mostly used with `sublanguage` to build up - * a single large buffer than can be parsed by sublanguage. - * - * - The mode begin ands ends normally. - * - Content matched is added to the parent mode buffer. - * - The parser cursor is moved forward normally. - * - * @abort - A hack placeholder until we have ignore. Aborts the mode (as if it - * never matched) but DOES NOT continue to match subsequent `contains` - * modes. Abort is bad/suboptimal because it can result in modes - * farther down not getting applied because an earlier rule eats the - * content but then aborts. - * - * - The mode does not begin. - * - Content matched by `begin` is added to the mode buffer. - * - The parser cursor is moved forward accordingly. - * - * @ignore - Ignores the mode (as if it never matched) and continues to match any - * subsequent `contains` modes. Ignore isn't technically possible with - * the current parser implementation. - * - * - The mode does not begin. - * - Content matched by `begin` is ignored. - * - The parser cursor is not moved forward. - */ - - /** - * Compiles an individual mode - * - * This can raise an error if the mode contains certain detectable known logic - * issues. - * @param {Mode} mode - * @param {CompiledMode | null} [parent] - * @returns {CompiledMode | never} - */ - function compileMode(mode, parent) { - const cmode = /** @type CompiledMode */ (mode); - if (mode.isCompiled) return cmode; - - [ - scopeClassName, - // do this early so compiler extensions generally don't have to worry about - // the distinction between match/begin - compileMatch, - MultiClass, - beforeMatchExt - ].forEach(ext => ext(mode, parent)); - - language.compilerExtensions.forEach(ext => ext(mode, parent)); - - // __beforeBegin is considered private API, internal use only - mode.__beforeBegin = null; - - [ - beginKeywords, - // do this later so compiler extensions that come earlier have access to the - // raw array if they wanted to perhaps manipulate it, etc. - compileIllegal, - // default to 1 relevance if not specified - compileRelevance - ].forEach(ext => ext(mode, parent)); - - mode.isCompiled = true; - - let keywordPattern = null; - if (typeof mode.keywords === "object" && mode.keywords.$pattern) { - // we need a copy because keywords might be compiled multiple times - // so we can't go deleting $pattern from the original on the first - // pass - mode.keywords = Object.assign({}, mode.keywords); - keywordPattern = mode.keywords.$pattern; - delete mode.keywords.$pattern; - } - keywordPattern = keywordPattern || /\w+/; - - if (mode.keywords) { - mode.keywords = compileKeywords(mode.keywords, language.case_insensitive); - } - - cmode.keywordPatternRe = langRe(keywordPattern, true); - - if (parent) { - if (!mode.begin) mode.begin = /\B|\b/; - cmode.beginRe = langRe(cmode.begin); - if (!mode.end && !mode.endsWithParent) mode.end = /\B|\b/; - if (mode.end) cmode.endRe = langRe(cmode.end); - cmode.terminatorEnd = source(cmode.end) || ''; - if (mode.endsWithParent && parent.terminatorEnd) { - cmode.terminatorEnd += (mode.end ? '|' : '') + parent.terminatorEnd; - } - } - if (mode.illegal) cmode.illegalRe = langRe(/** @type {RegExp | string} */ (mode.illegal)); - if (!mode.contains) mode.contains = []; - - mode.contains = [].concat(...mode.contains.map(function(c) { - return expandOrCloneMode(c === 'self' ? mode : c); - })); - mode.contains.forEach(function(c) { compileMode(/** @type Mode */ (c), cmode); }); - - if (mode.starts) { - compileMode(mode.starts, parent); - } - - cmode.matcher = buildModeRegex(cmode); - return cmode; - } - - if (!language.compilerExtensions) language.compilerExtensions = []; - - // self is not valid at the top-level - if (language.contains && language.contains.includes('self')) { - throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation."); - } - - // we need a null object, which inherit will guarantee - language.classNameAliases = inherit$1(language.classNameAliases || {}); - - return compileMode(/** @type Mode */ (language)); -} - -/** - * Determines if a mode has a dependency on it's parent or not - * - * If a mode does have a parent dependency then often we need to clone it if - * it's used in multiple places so that each copy points to the correct parent, - * where-as modes without a parent can often safely be re-used at the bottom of - * a mode chain. - * - * @param {Mode | null} mode - * @returns {boolean} - is there a dependency on the parent? - * */ -function dependencyOnParent(mode) { - if (!mode) return false; - - return mode.endsWithParent || dependencyOnParent(mode.starts); -} - -/** - * Expands a mode or clones it if necessary - * - * This is necessary for modes with parental dependenceis (see notes on - * `dependencyOnParent`) and for nodes that have `variants` - which must then be - * exploded into their own individual modes at compile time. - * - * @param {Mode} mode - * @returns {Mode | Mode[]} - * */ -function expandOrCloneMode(mode) { - if (mode.variants && !mode.cachedVariants) { - mode.cachedVariants = mode.variants.map(function(variant) { - return inherit$1(mode, { variants: null }, variant); - }); - } - - // EXPAND - // if we have variants then essentially "replace" the mode with the variants - // this happens in compileMode, where this function is called from - if (mode.cachedVariants) { - return mode.cachedVariants; - } - - // CLONE - // if we have dependencies on parents then we need a unique - // instance of ourselves, so we can be reused with many - // different parents without issue - if (dependencyOnParent(mode)) { - return inherit$1(mode, { starts: mode.starts ? inherit$1(mode.starts) : null }); - } - - if (Object.isFrozen(mode)) { - return inherit$1(mode); - } - - // no special dependency issues, just return ourselves - return mode; -} - -var version = "11.5.0"; - -class HTMLInjectionError extends Error { - constructor(reason, html) { - super(reason); - this.name = "HTMLInjectionError"; - this.html = html; - } -} - -/* -Syntax highlighting with language autodetection. -https://highlightjs.org/ -*/ - -/** -@typedef {import('highlight.js').Mode} Mode -@typedef {import('highlight.js').CompiledMode} CompiledMode -@typedef {import('highlight.js').CompiledScope} CompiledScope -@typedef {import('highlight.js').Language} Language -@typedef {import('highlight.js').HLJSApi} HLJSApi -@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin -@typedef {import('highlight.js').PluginEvent} PluginEvent -@typedef {import('highlight.js').HLJSOptions} HLJSOptions -@typedef {import('highlight.js').LanguageFn} LanguageFn -@typedef {import('highlight.js').HighlightedHTMLElement} HighlightedHTMLElement -@typedef {import('highlight.js').BeforeHighlightContext} BeforeHighlightContext -@typedef {import('highlight.js/private').MatchType} MatchType -@typedef {import('highlight.js/private').KeywordData} KeywordData -@typedef {import('highlight.js/private').EnhancedMatch} EnhancedMatch -@typedef {import('highlight.js/private').AnnotatedError} AnnotatedError -@typedef {import('highlight.js').AutoHighlightResult} AutoHighlightResult -@typedef {import('highlight.js').HighlightOptions} HighlightOptions -@typedef {import('highlight.js').HighlightResult} HighlightResult -*/ - - -const escape = escapeHTML; -const inherit = inherit$1; -const NO_MATCH = Symbol("nomatch"); -const MAX_KEYWORD_HITS = 7; - -/** - * @param {any} hljs - object that is extended (legacy) - * @returns {HLJSApi} - */ -const HLJS = function(hljs) { - // Global internal variables used within the highlight.js library. - /** @type {Record} */ - const languages = Object.create(null); - /** @type {Record} */ - const aliases = Object.create(null); - /** @type {HLJSPlugin[]} */ - const plugins = []; - - // safe/production mode - swallows more errors, tries to keep running - // even if a single syntax or parse hits a fatal error - let SAFE_MODE = true; - const LANGUAGE_NOT_FOUND = "Could not find the language '{}', did you forget to load/include a language module?"; - /** @type {Language} */ - const PLAINTEXT_LANGUAGE = { disableAutodetect: true, name: 'Plain text', contains: [] }; - - // Global options used when within external APIs. This is modified when - // calling the `hljs.configure` function. - /** @type HLJSOptions */ - let options = { - ignoreUnescapedHTML: false, - throwUnescapedHTML: false, - noHighlightRe: /^(no-?highlight)$/i, - languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i, - classPrefix: 'hljs-', - cssSelector: 'pre code', - languages: null, - // beta configuration options, subject to change, welcome to discuss - // https://github.com/highlightjs/highlight.js/issues/1086 - __emitter: TokenTreeEmitter - }; - - /* Utility functions */ - - /** - * Tests a language name to see if highlighting should be skipped - * @param {string} languageName - */ - function shouldNotHighlight(languageName) { - return options.noHighlightRe.test(languageName); - } - - /** - * @param {HighlightedHTMLElement} block - the HTML element to determine language for - */ - function blockLanguage(block) { - let classes = block.className + ' '; - - classes += block.parentNode ? block.parentNode.className : ''; - - // language-* takes precedence over non-prefixed class names. - const match = options.languageDetectRe.exec(classes); - if (match) { - const language = getLanguage(match[1]); - if (!language) { - warn(LANGUAGE_NOT_FOUND.replace("{}", match[1])); - warn("Falling back to no-highlight mode for this block.", block); - } - return language ? match[1] : 'no-highlight'; - } - - return classes - .split(/\s+/) - .find((_class) => shouldNotHighlight(_class) || getLanguage(_class)); - } - - /** - * Core highlighting function. - * - * OLD API - * highlight(lang, code, ignoreIllegals, continuation) - * - * NEW API - * highlight(code, {lang, ignoreIllegals}) - * - * @param {string} codeOrLanguageName - the language to use for highlighting - * @param {string | HighlightOptions} optionsOrCode - the code to highlight - * @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail - * - * @returns {HighlightResult} Result - an object that represents the result - * @property {string} language - the language name - * @property {number} relevance - the relevance score - * @property {string} value - the highlighted HTML code - * @property {string} code - the original raw code - * @property {CompiledMode} top - top of the current mode stack - * @property {boolean} illegal - indicates whether any illegal matches were found - */ - function highlight(codeOrLanguageName, optionsOrCode, ignoreIllegals) { - let code = ""; - let languageName = ""; - if (typeof optionsOrCode === "object") { - code = codeOrLanguageName; - ignoreIllegals = optionsOrCode.ignoreIllegals; - languageName = optionsOrCode.language; - } else { - // old API - deprecated("10.7.0", "highlight(lang, code, ...args) has been deprecated."); - deprecated("10.7.0", "Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"); - languageName = codeOrLanguageName; - code = optionsOrCode; - } - - // https://github.com/highlightjs/highlight.js/issues/3149 - // eslint-disable-next-line no-undefined - if (ignoreIllegals === undefined) { ignoreIllegals = true; } - - /** @type {BeforeHighlightContext} */ - const context = { - code, - language: languageName - }; - // the plugin can change the desired language or the code to be highlighted - // just be changing the object it was passed - fire("before:highlight", context); - - // a before plugin can usurp the result completely by providing it's own - // in which case we don't even need to call highlight - const result = context.result - ? context.result - : _highlight(context.language, context.code, ignoreIllegals); - - result.code = context.code; - // the plugin can change anything in result to suite it - fire("after:highlight", result); - - return result; - } - - /** - * private highlight that's used internally and does not fire callbacks - * - * @param {string} languageName - the language to use for highlighting - * @param {string} codeToHighlight - the code to highlight - * @param {boolean?} [ignoreIllegals] - whether to ignore illegal matches, default is to bail - * @param {CompiledMode?} [continuation] - current continuation mode, if any - * @returns {HighlightResult} - result of the highlight operation - */ - function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) { - const keywordHits = Object.create(null); - - /** - * Return keyword data if a match is a keyword - * @param {CompiledMode} mode - current mode - * @param {string} matchText - the textual match - * @returns {KeywordData | false} - */ - function keywordData(mode, matchText) { - return mode.keywords[matchText]; - } - - function processKeywords() { - if (!top.keywords) { - emitter.addText(modeBuffer); - return; - } - - let lastIndex = 0; - top.keywordPatternRe.lastIndex = 0; - let match = top.keywordPatternRe.exec(modeBuffer); - let buf = ""; - - while (match) { - buf += modeBuffer.substring(lastIndex, match.index); - const word = language.case_insensitive ? match[0].toLowerCase() : match[0]; - const data = keywordData(top, word); - if (data) { - const [kind, keywordRelevance] = data; - emitter.addText(buf); - buf = ""; - - keywordHits[word] = (keywordHits[word] || 0) + 1; - if (keywordHits[word] <= MAX_KEYWORD_HITS) relevance += keywordRelevance; - if (kind.startsWith("_")) { - // _ implied for relevance only, do not highlight - // by applying a class name - buf += match[0]; - } else { - const cssClass = language.classNameAliases[kind] || kind; - emitter.addKeyword(match[0], cssClass); - } - } else { - buf += match[0]; - } - lastIndex = top.keywordPatternRe.lastIndex; - match = top.keywordPatternRe.exec(modeBuffer); - } - buf += modeBuffer.substr(lastIndex); - emitter.addText(buf); - } - - function processSubLanguage() { - if (modeBuffer === "") return; - /** @type HighlightResult */ - let result = null; - - if (typeof top.subLanguage === 'string') { - if (!languages[top.subLanguage]) { - emitter.addText(modeBuffer); - return; - } - result = _highlight(top.subLanguage, modeBuffer, true, continuations[top.subLanguage]); - continuations[top.subLanguage] = /** @type {CompiledMode} */ (result._top); - } else { - result = highlightAuto(modeBuffer, top.subLanguage.length ? top.subLanguage : null); - } - - // Counting embedded language score towards the host language may be disabled - // with zeroing the containing mode relevance. Use case in point is Markdown that - // allows XML everywhere and makes every XML snippet to have a much larger Markdown - // score. - if (top.relevance > 0) { - relevance += result.relevance; - } - emitter.addSublanguage(result._emitter, result.language); - } - - function processBuffer() { - if (top.subLanguage != null) { - processSubLanguage(); - } else { - processKeywords(); - } - modeBuffer = ''; - } - - /** - * @param {CompiledScope} scope - * @param {RegExpMatchArray} match - */ - function emitMultiClass(scope, match) { - let i = 1; - const max = match.length - 1; - while (i <= max) { - if (!scope._emit[i]) { i++; continue; } - const klass = language.classNameAliases[scope[i]] || scope[i]; - const text = match[i]; - if (klass) { - emitter.addKeyword(text, klass); - } else { - modeBuffer = text; - processKeywords(); - modeBuffer = ""; - } - i++; - } - } - - /** - * @param {CompiledMode} mode - new mode to start - * @param {RegExpMatchArray} match - */ - function startNewMode(mode, match) { - if (mode.scope && typeof mode.scope === "string") { - emitter.openNode(language.classNameAliases[mode.scope] || mode.scope); - } - if (mode.beginScope) { - // beginScope just wraps the begin match itself in a scope - if (mode.beginScope._wrap) { - emitter.addKeyword(modeBuffer, language.classNameAliases[mode.beginScope._wrap] || mode.beginScope._wrap); - modeBuffer = ""; - } else if (mode.beginScope._multi) { - // at this point modeBuffer should just be the match - emitMultiClass(mode.beginScope, match); - modeBuffer = ""; - } - } - - top = Object.create(mode, { parent: { value: top } }); - return top; - } - - /** - * @param {CompiledMode } mode - the mode to potentially end - * @param {RegExpMatchArray} match - the latest match - * @param {string} matchPlusRemainder - match plus remainder of content - * @returns {CompiledMode | void} - the next mode, or if void continue on in current mode - */ - function endOfMode(mode, match, matchPlusRemainder) { - let matched = startsWith(mode.endRe, matchPlusRemainder); - - if (matched) { - if (mode["on:end"]) { - const resp = new Response(mode); - mode["on:end"](match, resp); - if (resp.isMatchIgnored) matched = false; - } - - if (matched) { - while (mode.endsParent && mode.parent) { - mode = mode.parent; - } - return mode; - } - } - // even if on:end fires an `ignore` it's still possible - // that we might trigger the end node because of a parent mode - if (mode.endsWithParent) { - return endOfMode(mode.parent, match, matchPlusRemainder); - } - } - - /** - * Handle matching but then ignoring a sequence of text - * - * @param {string} lexeme - string containing full match text - */ - function doIgnore(lexeme) { - if (top.matcher.regexIndex === 0) { - // no more regexes to potentially match here, so we move the cursor forward one - // space - modeBuffer += lexeme[0]; - return 1; - } else { - // no need to move the cursor, we still have additional regexes to try and - // match at this very spot - resumeScanAtSamePosition = true; - return 0; - } - } - - /** - * Handle the start of a new potential mode match - * - * @param {EnhancedMatch} match - the current match - * @returns {number} how far to advance the parse cursor - */ - function doBeginMatch(match) { - const lexeme = match[0]; - const newMode = match.rule; - - const resp = new Response(newMode); - // first internal before callbacks, then the public ones - const beforeCallbacks = [newMode.__beforeBegin, newMode["on:begin"]]; - for (const cb of beforeCallbacks) { - if (!cb) continue; - cb(match, resp); - if (resp.isMatchIgnored) return doIgnore(lexeme); - } - - if (newMode.skip) { - modeBuffer += lexeme; - } else { - if (newMode.excludeBegin) { - modeBuffer += lexeme; - } - processBuffer(); - if (!newMode.returnBegin && !newMode.excludeBegin) { - modeBuffer = lexeme; - } - } - startNewMode(newMode, match); - return newMode.returnBegin ? 0 : lexeme.length; - } - - /** - * Handle the potential end of mode - * - * @param {RegExpMatchArray} match - the current match - */ - function doEndMatch(match) { - const lexeme = match[0]; - const matchPlusRemainder = codeToHighlight.substr(match.index); - - const endMode = endOfMode(top, match, matchPlusRemainder); - if (!endMode) { return NO_MATCH; } - - const origin = top; - if (top.endScope && top.endScope._wrap) { - processBuffer(); - emitter.addKeyword(lexeme, top.endScope._wrap); - } else if (top.endScope && top.endScope._multi) { - processBuffer(); - emitMultiClass(top.endScope, match); - } else if (origin.skip) { - modeBuffer += lexeme; - } else { - if (!(origin.returnEnd || origin.excludeEnd)) { - modeBuffer += lexeme; - } - processBuffer(); - if (origin.excludeEnd) { - modeBuffer = lexeme; - } - } - do { - if (top.scope) { - emitter.closeNode(); - } - if (!top.skip && !top.subLanguage) { - relevance += top.relevance; - } - top = top.parent; - } while (top !== endMode.parent); - if (endMode.starts) { - startNewMode(endMode.starts, match); - } - return origin.returnEnd ? 0 : lexeme.length; - } - - function processContinuations() { - const list = []; - for (let current = top; current !== language; current = current.parent) { - if (current.scope) { - list.unshift(current.scope); - } - } - list.forEach(item => emitter.openNode(item)); - } - - /** @type {{type?: MatchType, index?: number, rule?: Mode}}} */ - let lastMatch = {}; - - /** - * Process an individual match - * - * @param {string} textBeforeMatch - text preceding the match (since the last match) - * @param {EnhancedMatch} [match] - the match itself - */ - function processLexeme(textBeforeMatch, match) { - const lexeme = match && match[0]; - - // add non-matched text to the current mode buffer - modeBuffer += textBeforeMatch; - - if (lexeme == null) { - processBuffer(); - return 0; - } - - // we've found a 0 width match and we're stuck, so we need to advance - // this happens when we have badly behaved rules that have optional matchers to the degree that - // sometimes they can end up matching nothing at all - // Ref: https://github.com/highlightjs/highlight.js/issues/2140 - if (lastMatch.type === "begin" && match.type === "end" && lastMatch.index === match.index && lexeme === "") { - // spit the "skipped" character that our regex choked on back into the output sequence - modeBuffer += codeToHighlight.slice(match.index, match.index + 1); - if (!SAFE_MODE) { - /** @type {AnnotatedError} */ - const err = new Error(`0 width match regex (${languageName})`); - err.languageName = languageName; - err.badRule = lastMatch.rule; - throw err; - } - return 1; - } - lastMatch = match; - - if (match.type === "begin") { - return doBeginMatch(match); - } else if (match.type === "illegal" && !ignoreIllegals) { - // illegal match, we do not continue processing - /** @type {AnnotatedError} */ - const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.scope || '') + '"'); - err.mode = top; - throw err; - } else if (match.type === "end") { - const processed = doEndMatch(match); - if (processed !== NO_MATCH) { - return processed; - } - } - - // edge case for when illegal matches $ (end of line) which is technically - // a 0 width match but not a begin/end match so it's not caught by the - // first handler (when ignoreIllegals is true) - if (match.type === "illegal" && lexeme === "") { - // advance so we aren't stuck in an infinite loop - return 1; - } - - // infinite loops are BAD, this is a last ditch catch all. if we have a - // decent number of iterations yet our index (cursor position in our - // parsing) still 3x behind our index then something is very wrong - // so we bail - if (iterations > 100000 && iterations > match.index * 3) { - const err = new Error('potential infinite loop, way more iterations than matches'); - throw err; - } - - /* - Why might be find ourselves here? An potential end match that was - triggered but could not be completed. IE, `doEndMatch` returned NO_MATCH. - (this could be because a callback requests the match be ignored, etc) - - This causes no real harm other than stopping a few times too many. - */ - - modeBuffer += lexeme; - return lexeme.length; - } - - const language = getLanguage(languageName); - if (!language) { - error(LANGUAGE_NOT_FOUND.replace("{}", languageName)); - throw new Error('Unknown language: "' + languageName + '"'); - } - - const md = compileLanguage(language); - let result = ''; - /** @type {CompiledMode} */ - let top = continuation || md; - /** @type Record */ - const continuations = {}; // keep continuations for sub-languages - const emitter = new options.__emitter(options); - processContinuations(); - let modeBuffer = ''; - let relevance = 0; - let index = 0; - let iterations = 0; - let resumeScanAtSamePosition = false; - - try { - top.matcher.considerAll(); - - for (;;) { - iterations++; - if (resumeScanAtSamePosition) { - // only regexes not matched previously will now be - // considered for a potential match - resumeScanAtSamePosition = false; - } else { - top.matcher.considerAll(); - } - top.matcher.lastIndex = index; - - const match = top.matcher.exec(codeToHighlight); - // console.log("match", match[0], match.rule && match.rule.begin) - - if (!match) break; - - const beforeMatch = codeToHighlight.substring(index, match.index); - const processedCount = processLexeme(beforeMatch, match); - index = match.index + processedCount; - } - processLexeme(codeToHighlight.substr(index)); - emitter.closeAllNodes(); - emitter.finalize(); - result = emitter.toHTML(); - - return { - language: languageName, - value: result, - relevance: relevance, - illegal: false, - _emitter: emitter, - _top: top - }; - } catch (err) { - if (err.message && err.message.includes('Illegal')) { - return { - language: languageName, - value: escape(codeToHighlight), - illegal: true, - relevance: 0, - _illegalBy: { - message: err.message, - index: index, - context: codeToHighlight.slice(index - 100, index + 100), - mode: err.mode, - resultSoFar: result - }, - _emitter: emitter - }; - } else if (SAFE_MODE) { - return { - language: languageName, - value: escape(codeToHighlight), - illegal: false, - relevance: 0, - errorRaised: err, - _emitter: emitter, - _top: top - }; - } else { - throw err; - } - } - } - - /** - * returns a valid highlight result, without actually doing any actual work, - * auto highlight starts with this and it's possible for small snippets that - * auto-detection may not find a better match - * @param {string} code - * @returns {HighlightResult} - */ - function justTextHighlightResult(code) { - const result = { - value: escape(code), - illegal: false, - relevance: 0, - _top: PLAINTEXT_LANGUAGE, - _emitter: new options.__emitter(options) - }; - result._emitter.addText(code); - return result; - } - - /** - Highlighting with language detection. Accepts a string with the code to - highlight. Returns an object with the following properties: - - - language (detected language) - - relevance (int) - - value (an HTML string with highlighting markup) - - secondBest (object with the same structure for second-best heuristically - detected language, may be absent) - - @param {string} code - @param {Array} [languageSubset] - @returns {AutoHighlightResult} - */ - function highlightAuto(code, languageSubset) { - languageSubset = languageSubset || options.languages || Object.keys(languages); - const plaintext = justTextHighlightResult(code); - - const results = languageSubset.filter(getLanguage).filter(autoDetection).map(name => - _highlight(name, code, false) - ); - results.unshift(plaintext); // plaintext is always an option - - const sorted = results.sort((a, b) => { - // sort base on relevance - if (a.relevance !== b.relevance) return b.relevance - a.relevance; - - // always award the tie to the base language - // ie if C++ and Arduino are tied, it's more likely to be C++ - if (a.language && b.language) { - if (getLanguage(a.language).supersetOf === b.language) { - return 1; - } else if (getLanguage(b.language).supersetOf === a.language) { - return -1; - } - } - - // otherwise say they are equal, which has the effect of sorting on - // relevance while preserving the original ordering - which is how ties - // have historically been settled, ie the language that comes first always - // wins in the case of a tie - return 0; - }); - - const [best, secondBest] = sorted; - - /** @type {AutoHighlightResult} */ - const result = best; - result.secondBest = secondBest; - - return result; - } - - /** - * Builds new class name for block given the language name - * - * @param {HTMLElement} element - * @param {string} [currentLang] - * @param {string} [resultLang] - */ - function updateClassName(element, currentLang, resultLang) { - const language = (currentLang && aliases[currentLang]) || resultLang; - - element.classList.add("hljs"); - element.classList.add(`language-${language}`); - } - - /** - * Applies highlighting to a DOM node containing code. - * - * @param {HighlightedHTMLElement} element - the HTML element to highlight - */ - function highlightElement(element) { - /** @type HTMLElement */ - let node = null; - const language = blockLanguage(element); - - if (shouldNotHighlight(language)) return; - - fire("before:highlightElement", - { el: element, language: language }); - - // we should be all text, no child nodes (unescaped HTML) - this is possibly - // an HTML injection attack - it's likely too late if this is already in - // production (the code has likely already done its damage by the time - // we're seeing it)... but we yell loudly about this so that hopefully it's - // more likely to be caught in development before making it to production - if (element.children.length > 0) { - if (!options.ignoreUnescapedHTML) { - console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."); - console.warn("https://github.com/highlightjs/highlight.js/wiki/security"); - console.warn("The element with unescaped HTML:"); - console.warn(element); - } - if (options.throwUnescapedHTML) { - const err = new HTMLInjectionError( - "One of your code blocks includes unescaped HTML.", - element.innerHTML - ); - throw err; - } - } - - node = element; - const text = node.textContent; - const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text); - - element.innerHTML = result.value; - updateClassName(element, language, result.language); - element.result = { - language: result.language, - // TODO: remove with version 11.0 - re: result.relevance, - relevance: result.relevance - }; - if (result.secondBest) { - element.secondBest = { - language: result.secondBest.language, - relevance: result.secondBest.relevance - }; - } - - fire("after:highlightElement", { el: element, result, text }); - } - - /** - * Updates highlight.js global options with the passed options - * - * @param {Partial} userOptions - */ - function configure(userOptions) { - options = inherit(options, userOptions); - } - - // TODO: remove v12, deprecated - const initHighlighting = () => { - highlightAll(); - deprecated("10.6.0", "initHighlighting() deprecated. Use highlightAll() now."); - }; - - // TODO: remove v12, deprecated - function initHighlightingOnLoad() { - highlightAll(); - deprecated("10.6.0", "initHighlightingOnLoad() deprecated. Use highlightAll() now."); - } - - let wantsHighlight = false; - - /** - * auto-highlights all pre>code elements on the page - */ - function highlightAll() { - // if we are called too early in the loading process - if (document.readyState === "loading") { - wantsHighlight = true; - return; - } - - const blocks = document.querySelectorAll(options.cssSelector); - blocks.forEach(highlightElement); - } - - function boot() { - // if a highlight was requested before DOM was loaded, do now - if (wantsHighlight) highlightAll(); - } - - // make sure we are in the browser environment - if (typeof window !== 'undefined' && window.addEventListener) { - window.addEventListener('DOMContentLoaded', boot, false); - } - - /** - * Register a language grammar module - * - * @param {string} languageName - * @param {LanguageFn} languageDefinition - */ - function registerLanguage(languageName, languageDefinition) { - let lang = null; - try { - lang = languageDefinition(hljs); - } catch (error$1) { - error("Language definition for '{}' could not be registered.".replace("{}", languageName)); - // hard or soft error - if (!SAFE_MODE) { throw error$1; } else { error(error$1); } - // languages that have serious errors are replaced with essentially a - // "plaintext" stand-in so that the code blocks will still get normal - // css classes applied to them - and one bad language won't break the - // entire highlighter - lang = PLAINTEXT_LANGUAGE; - } - // give it a temporary name if it doesn't have one in the meta-data - if (!lang.name) lang.name = languageName; - languages[languageName] = lang; - lang.rawDefinition = languageDefinition.bind(null, hljs); - - if (lang.aliases) { - registerAliases(lang.aliases, { languageName }); - } - } - - /** - * Remove a language grammar module - * - * @param {string} languageName - */ - function unregisterLanguage(languageName) { - delete languages[languageName]; - for (const alias of Object.keys(aliases)) { - if (aliases[alias] === languageName) { - delete aliases[alias]; - } - } - } - - /** - * @returns {string[]} List of language internal names - */ - function listLanguages() { - return Object.keys(languages); - } - - /** - * @param {string} name - name of the language to retrieve - * @returns {Language | undefined} - */ - function getLanguage(name) { - name = (name || '').toLowerCase(); - return languages[name] || languages[aliases[name]]; - } - - /** - * - * @param {string|string[]} aliasList - single alias or list of aliases - * @param {{languageName: string}} opts - */ - function registerAliases(aliasList, { languageName }) { - if (typeof aliasList === 'string') { - aliasList = [aliasList]; - } - aliasList.forEach(alias => { aliases[alias.toLowerCase()] = languageName; }); - } - - /** - * Determines if a given language has auto-detection enabled - * @param {string} name - name of the language - */ - function autoDetection(name) { - const lang = getLanguage(name); - return lang && !lang.disableAutodetect; - } - - /** - * Upgrades the old highlightBlock plugins to the new - * highlightElement API - * @param {HLJSPlugin} plugin - */ - function upgradePluginAPI(plugin) { - // TODO: remove with v12 - if (plugin["before:highlightBlock"] && !plugin["before:highlightElement"]) { - plugin["before:highlightElement"] = (data) => { - plugin["before:highlightBlock"]( - Object.assign({ block: data.el }, data) - ); - }; - } - if (plugin["after:highlightBlock"] && !plugin["after:highlightElement"]) { - plugin["after:highlightElement"] = (data) => { - plugin["after:highlightBlock"]( - Object.assign({ block: data.el }, data) - ); - }; - } - } - - /** - * @param {HLJSPlugin} plugin - */ - function addPlugin(plugin) { - upgradePluginAPI(plugin); - plugins.push(plugin); - } - - /** - * - * @param {PluginEvent} event - * @param {any} args - */ - function fire(event, args) { - const cb = event; - plugins.forEach(function(plugin) { - if (plugin[cb]) { - plugin[cb](args); - } - }); - } - - /** - * DEPRECATED - * @param {HighlightedHTMLElement} el - */ - function deprecateHighlightBlock(el) { - deprecated("10.7.0", "highlightBlock will be removed entirely in v12.0"); - deprecated("10.7.0", "Please use highlightElement now."); - - return highlightElement(el); - } - - /* Interface definition */ - Object.assign(hljs, { - highlight, - highlightAuto, - highlightAll, - highlightElement, - // TODO: Remove with v12 API - highlightBlock: deprecateHighlightBlock, - configure, - initHighlighting, - initHighlightingOnLoad, - registerLanguage, - unregisterLanguage, - listLanguages, - getLanguage, - registerAliases, - autoDetection, - inherit, - addPlugin - }); - - hljs.debugMode = function() { SAFE_MODE = false; }; - hljs.safeMode = function() { SAFE_MODE = true; }; - hljs.versionString = version; - - hljs.regex = { - concat: concat, - lookahead: lookahead, - either: either, - optional: optional, - anyNumberOfTimes: anyNumberOfTimes - }; - - for (const key in MODES) { - // @ts-ignore - if (typeof MODES[key] === "object") { - // @ts-ignore - deepFreeze$1(MODES[key]); - } - } - - // merge all the modes/regexes into our main object - Object.assign(hljs, MODES); - - return hljs; -}; - -// export an "instance" of the highlighter -var highlight = HLJS({}); - -var core = highlight; -highlight.HighlightJS = highlight; -highlight.default = highlight; - -const IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*'; -const KEYWORDS = [ - "as", // for exports - "in", - "of", - "if", - "for", - "while", - "finally", - "var", - "new", - "function", - "do", - "return", - "void", - "else", - "break", - "catch", - "instanceof", - "with", - "throw", - "case", - "default", - "try", - "switch", - "continue", - "typeof", - "delete", - "let", - "yield", - "const", - "class", - // JS handles these with a special rule - // "get", - // "set", - "debugger", - "async", - "await", - "static", - "import", - "from", - "export", - "extends" -]; -const LITERALS = [ - "true", - "false", - "null", - "undefined", - "NaN", - "Infinity" -]; - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects -const TYPES = [ - // Fundamental objects - "Object", - "Function", - "Boolean", - "Symbol", - // numbers and dates - "Math", - "Date", - "Number", - "BigInt", - // text - "String", - "RegExp", - // Indexed collections - "Array", - "Float32Array", - "Float64Array", - "Int8Array", - "Uint8Array", - "Uint8ClampedArray", - "Int16Array", - "Int32Array", - "Uint16Array", - "Uint32Array", - "BigInt64Array", - "BigUint64Array", - // Keyed collections - "Set", - "Map", - "WeakSet", - "WeakMap", - // Structured data - "ArrayBuffer", - "SharedArrayBuffer", - "Atomics", - "DataView", - "JSON", - // Control abstraction objects - "Promise", - "Generator", - "GeneratorFunction", - "AsyncFunction", - // Reflection - "Reflect", - "Proxy", - // Internationalization - "Intl", - // WebAssembly - "WebAssembly" -]; - -const ERROR_TYPES = [ - "Error", - "EvalError", - "InternalError", - "RangeError", - "ReferenceError", - "SyntaxError", - "TypeError", - "URIError" -]; - -const BUILT_IN_GLOBALS = [ - "setInterval", - "setTimeout", - "clearInterval", - "clearTimeout", - - "require", - "exports", - - "eval", - "isFinite", - "isNaN", - "parseFloat", - "parseInt", - "decodeURI", - "decodeURIComponent", - "encodeURI", - "encodeURIComponent", - "escape", - "unescape" -]; - -const BUILT_IN_VARIABLES = [ - "arguments", - "this", - "super", - "console", - "window", - "document", - "localStorage", - "module", - "global" // Node.js -]; - -const BUILT_INS = [].concat( - BUILT_IN_GLOBALS, - TYPES, - ERROR_TYPES -); - -/* -Language: JavaScript -Description: JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions. -Category: common, scripting, web -Website: https://developer.mozilla.org/en-US/docs/Web/JavaScript -*/ - -/** @type LanguageFn */ -function javascript(hljs) { - const regex = hljs.regex; - /** - * Takes a string like " { - const tag = "', - end: '' - }; - // to avoid some special cases inside isTrulyOpeningTag - const XML_SELF_CLOSING = /<[A-Za-z0-9\\._:-]+\s*\/>/; - const XML_TAG = { - begin: /<[A-Za-z0-9\\._:-]+/, - end: /\/[A-Za-z0-9\\._:-]+>|\/>/, - /** - * @param {RegExpMatchArray} match - * @param {CallbackResponse} response - */ - isTrulyOpeningTag: (match, response) => { - const afterMatchIndex = match[0].length + match.index; - const nextChar = match.input[afterMatchIndex]; - if ( - // HTML should not include another raw `<` inside a tag - // nested type? - // `>`, etc. - nextChar === "<" || - // the , gives away that this is not HTML - // `` - nextChar === ",") { - response.ignoreMatch(); - return; - } - - // `` - // Quite possibly a tag, lets look for a matching closing tag... - if (nextChar === ">") { - // if we cannot find a matching closing tag, then we - // will ignore it - if (!hasClosingTag(match, { after: afterMatchIndex })) { - response.ignoreMatch(); - } - } - - // `` (self-closing) - // handled by simpleSelfClosing rule - - // `` - // technically this could be HTML, but it smells like a type - let m; - const afterMatch = match.input.substr(afterMatchIndex); - // NOTE: This is ugh, but added specifically for https://github.com/highlightjs/highlight.js/issues/3276 - if ((m = afterMatch.match(/^\s+extends\s+/))) { - if (m.index === 0) { - response.ignoreMatch(); - // eslint-disable-next-line no-useless-return - return; - } - } - } - }; - const KEYWORDS$1 = { - $pattern: IDENT_RE, - keyword: KEYWORDS, - literal: LITERALS, - built_in: BUILT_INS, - "variable.language": BUILT_IN_VARIABLES - }; - - // https://tc39.es/ecma262/#sec-literals-numeric-literals - const decimalDigits = '[0-9](_?[0-9])*'; - const frac = `\\.(${decimalDigits})`; - // DecimalIntegerLiteral, including Annex B NonOctalDecimalIntegerLiteral - // https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals - const decimalInteger = `0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*`; - const NUMBER = { - className: 'number', - variants: [ - // DecimalLiteral - { begin: `(\\b(${decimalInteger})((${frac})|\\.)?|(${frac}))` + - `[eE][+-]?(${decimalDigits})\\b` }, - { begin: `\\b(${decimalInteger})\\b((${frac})\\b|\\.)?|(${frac})\\b` }, - - // DecimalBigIntegerLiteral - { begin: `\\b(0|[1-9](_?[0-9])*)n\\b` }, - - // NonDecimalIntegerLiteral - { begin: "\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b" }, - { begin: "\\b0[bB][0-1](_?[0-1])*n?\\b" }, - { begin: "\\b0[oO][0-7](_?[0-7])*n?\\b" }, - - // LegacyOctalIntegerLiteral (does not include underscore separators) - // https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals - { begin: "\\b0[0-7]+n?\\b" }, - ], - relevance: 0 - }; - - const SUBST = { - className: 'subst', - begin: '\\$\\{', - end: '\\}', - keywords: KEYWORDS$1, - contains: [] // defined later - }; - const HTML_TEMPLATE = { - begin: 'html`', - end: '', - starts: { - end: '`', - returnEnd: false, - contains: [ - hljs.BACKSLASH_ESCAPE, - SUBST - ], - subLanguage: 'xml' - } - }; - const CSS_TEMPLATE = { - begin: 'css`', - end: '', - starts: { - end: '`', - returnEnd: false, - contains: [ - hljs.BACKSLASH_ESCAPE, - SUBST - ], - subLanguage: 'css' - } - }; - const TEMPLATE_STRING = { - className: 'string', - begin: '`', - end: '`', - contains: [ - hljs.BACKSLASH_ESCAPE, - SUBST - ] - }; - const JSDOC_COMMENT = hljs.COMMENT( - /\/\*\*(?!\/)/, - '\\*/', - { - relevance: 0, - contains: [ - { - begin: '(?=@[A-Za-z]+)', - relevance: 0, - contains: [ - { - className: 'doctag', - begin: '@[A-Za-z]+' - }, - { - className: 'type', - begin: '\\{', - end: '\\}', - excludeEnd: true, - excludeBegin: true, - relevance: 0 - }, - { - className: 'variable', - begin: IDENT_RE$1 + '(?=\\s*(-)|$)', - endsParent: true, - relevance: 0 - }, - // eat spaces (not newlines) so we can find - // types or variables - { - begin: /(?=[^\n])\s/, - relevance: 0 - } - ] - } - ] - } - ); - const COMMENT = { - className: "comment", - variants: [ - JSDOC_COMMENT, - hljs.C_BLOCK_COMMENT_MODE, - hljs.C_LINE_COMMENT_MODE - ] - }; - const SUBST_INTERNALS = [ - hljs.APOS_STRING_MODE, - hljs.QUOTE_STRING_MODE, - HTML_TEMPLATE, - CSS_TEMPLATE, - TEMPLATE_STRING, - NUMBER, - // This is intentional: - // See https://github.com/highlightjs/highlight.js/issues/3288 - // hljs.REGEXP_MODE - ]; - SUBST.contains = SUBST_INTERNALS - .concat({ - // we need to pair up {} inside our subst to prevent - // it from ending too early by matching another } - begin: /\{/, - end: /\}/, - keywords: KEYWORDS$1, - contains: [ - "self" - ].concat(SUBST_INTERNALS) - }); - const SUBST_AND_COMMENTS = [].concat(COMMENT, SUBST.contains); - const PARAMS_CONTAINS = SUBST_AND_COMMENTS.concat([ - // eat recursive parens in sub expressions - { - begin: /\(/, - end: /\)/, - keywords: KEYWORDS$1, - contains: ["self"].concat(SUBST_AND_COMMENTS) - } - ]); - const PARAMS = { - className: 'params', - begin: /\(/, - end: /\)/, - excludeBegin: true, - excludeEnd: true, - keywords: KEYWORDS$1, - contains: PARAMS_CONTAINS - }; - - // ES6 classes - const CLASS_OR_EXTENDS = { - variants: [ - // class Car extends vehicle - { - match: [ - /class/, - /\s+/, - IDENT_RE$1, - /\s+/, - /extends/, - /\s+/, - regex.concat(IDENT_RE$1, "(", regex.concat(/\./, IDENT_RE$1), ")*") - ], - scope: { - 1: "keyword", - 3: "title.class", - 5: "keyword", - 7: "title.class.inherited" - } - }, - // class Car - { - match: [ - /class/, - /\s+/, - IDENT_RE$1 - ], - scope: { - 1: "keyword", - 3: "title.class" - } - }, - - ] - }; - - const CLASS_REFERENCE = { - relevance: 0, - match: - regex.either( - // Hard coded exceptions - /\bJSON/, - // Float32Array, OutT - /\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/, - // CSSFactory, CSSFactoryT - /\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/, - // FPs, FPsT - /\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/, - // P - // single letters are not highlighted - // BLAH - // this will be flagged as a UPPER_CASE_CONSTANT instead - ), - className: "title.class", - keywords: { - _: [ - // se we still get relevance credit for JS library classes - ...TYPES, - ...ERROR_TYPES - ] - } - }; - - const USE_STRICT = { - label: "use_strict", - className: 'meta', - relevance: 10, - begin: /^\s*['"]use (strict|asm)['"]/ - }; - - const FUNCTION_DEFINITION = { - variants: [ - { - match: [ - /function/, - /\s+/, - IDENT_RE$1, - /(?=\s*\()/ - ] - }, - // anonymous function - { - match: [ - /function/, - /\s*(?=\()/ - ] - } - ], - className: { - 1: "keyword", - 3: "title.function" - }, - label: "func.def", - contains: [ PARAMS ], - illegal: /%/ - }; - - const UPPER_CASE_CONSTANT = { - relevance: 0, - match: /\b[A-Z][A-Z_0-9]+\b/, - className: "variable.constant" - }; - - function noneOf(list) { - return regex.concat("(?!", list.join("|"), ")"); - } - - const FUNCTION_CALL = { - match: regex.concat( - /\b/, - noneOf([ - ...BUILT_IN_GLOBALS, - "super" - ]), - IDENT_RE$1, regex.lookahead(/\(/)), - className: "title.function", - relevance: 0 - }; - - const PROPERTY_ACCESS = { - begin: regex.concat(/\./, regex.lookahead( - regex.concat(IDENT_RE$1, /(?![0-9A-Za-z$_(])/) - )), - end: IDENT_RE$1, - excludeBegin: true, - keywords: "prototype", - className: "property", - relevance: 0 - }; - - const GETTER_OR_SETTER = { - match: [ - /get|set/, - /\s+/, - IDENT_RE$1, - /(?=\()/ - ], - className: { - 1: "keyword", - 3: "title.function" - }, - contains: [ - { // eat to avoid empty params - begin: /\(\)/ - }, - PARAMS - ] - }; - - const FUNC_LEAD_IN_RE = '(\\(' + - '[^()]*(\\(' + - '[^()]*(\\(' + - '[^()]*' + - '\\)[^()]*)*' + - '\\)[^()]*)*' + - '\\)|' + hljs.UNDERSCORE_IDENT_RE + ')\\s*=>'; - - const FUNCTION_VARIABLE = { - match: [ - /const|var|let/, /\s+/, - IDENT_RE$1, /\s*/, - /=\s*/, - /(async\s*)?/, // async is optional - regex.lookahead(FUNC_LEAD_IN_RE) - ], - keywords: "async", - className: { - 1: "keyword", - 3: "title.function" - }, - contains: [ - PARAMS - ] - }; - - return { - name: 'Javascript', - aliases: ['js', 'jsx', 'mjs', 'cjs'], - keywords: KEYWORDS$1, - // this will be extended by TypeScript - exports: { PARAMS_CONTAINS, CLASS_REFERENCE }, - illegal: /#(?![$_A-z])/, - contains: [ - hljs.SHEBANG({ - label: "shebang", - binary: "node", - relevance: 5 - }), - USE_STRICT, - hljs.APOS_STRING_MODE, - hljs.QUOTE_STRING_MODE, - HTML_TEMPLATE, - CSS_TEMPLATE, - TEMPLATE_STRING, - COMMENT, - NUMBER, - CLASS_REFERENCE, - { - className: 'attr', - begin: IDENT_RE$1 + regex.lookahead(':'), - relevance: 0 - }, - FUNCTION_VARIABLE, - { // "value" container - begin: '(' + hljs.RE_STARTERS_RE + '|\\b(case|return|throw)\\b)\\s*', - keywords: 'return throw case', - relevance: 0, - contains: [ - COMMENT, - hljs.REGEXP_MODE, - { - className: 'function', - // we have to count the parens to make sure we actually have the - // correct bounding ( ) before the =>. There could be any number of - // sub-expressions inside also surrounded by parens. - begin: FUNC_LEAD_IN_RE, - returnBegin: true, - end: '\\s*=>', - contains: [ - { - className: 'params', - variants: [ - { - begin: hljs.UNDERSCORE_IDENT_RE, - relevance: 0 - }, - { - className: null, - begin: /\(\s*\)/, - skip: true - }, - { - begin: /\(/, - end: /\)/, - excludeBegin: true, - excludeEnd: true, - keywords: KEYWORDS$1, - contains: PARAMS_CONTAINS - } - ] - } - ] - }, - { // could be a comma delimited list of params to a function call - begin: /,/, - relevance: 0 - }, - { - match: /\s+/, - relevance: 0 - }, - { // JSX - variants: [ - { begin: FRAGMENT.begin, end: FRAGMENT.end }, - { match: XML_SELF_CLOSING }, - { - begin: XML_TAG.begin, - // we carefully check the opening tag to see if it truly - // is a tag and not a false positive - 'on:begin': XML_TAG.isTrulyOpeningTag, - end: XML_TAG.end - } - ], - subLanguage: 'xml', - contains: [ - { - begin: XML_TAG.begin, - end: XML_TAG.end, - skip: true, - contains: ['self'] - } - ] - } - ], - }, - FUNCTION_DEFINITION, - { - // prevent this from getting swallowed up by function - // since they appear "function like" - beginKeywords: "while if switch catch for" - }, - { - // we have to count the parens to make sure we actually have the correct - // bounding ( ). There could be any number of sub-expressions inside - // also surrounded by parens. - begin: '\\b(?!function)' + hljs.UNDERSCORE_IDENT_RE + - '\\(' + // first parens - '[^()]*(\\(' + - '[^()]*(\\(' + - '[^()]*' + - '\\)[^()]*)*' + - '\\)[^()]*)*' + - '\\)\\s*\\{', // end parens - returnBegin:true, - label: "func.def", - contains: [ - PARAMS, - hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE$1, className: "title.function" }) - ] - }, - // catch ... so it won't trigger the property rule below - { - match: /\.\.\./, - relevance: 0 - }, - PROPERTY_ACCESS, - // hack: prevents detection of keywords in some circumstances - // .keyword() - // $keyword = x - { - match: '\\$' + IDENT_RE$1, - relevance: 0 - }, - { - match: [ /\bconstructor(?=\s*\()/ ], - className: { 1: "title.function" }, - contains: [ PARAMS ] - }, - FUNCTION_CALL, - UPPER_CASE_CONSTANT, - CLASS_OR_EXTENDS, - GETTER_OR_SETTER, - { - match: /\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something` - } - ] - }; -} - -var javascript_1 = javascript; - -/* -Language: Python -Description: Python is an interpreted, object-oriented, high-level programming language with dynamic semantics. -Website: https://www.python.org -Category: common -*/ -function python(hljs) { - const regex = hljs.regex; - const IDENT_RE = /[\p{XID_Start}_]\p{XID_Continue}*/u; - const RESERVED_WORDS = [ - 'and', - 'as', - 'assert', - 'async', - 'await', - 'break', - 'class', - 'continue', - 'def', - 'del', - 'elif', - 'else', - 'except', - 'finally', - 'for', - 'from', - 'global', - 'if', - 'import', - 'in', - 'is', - 'lambda', - 'nonlocal|10', - 'not', - 'or', - 'pass', - 'raise', - 'return', - 'try', - 'while', - 'with', - 'yield' - ]; - - const BUILT_INS = [ - '__import__', - 'abs', - 'all', - 'any', - 'ascii', - 'bin', - 'bool', - 'breakpoint', - 'bytearray', - 'bytes', - 'callable', - 'chr', - 'classmethod', - 'compile', - 'complex', - 'delattr', - 'dict', - 'dir', - 'divmod', - 'enumerate', - 'eval', - 'exec', - 'filter', - 'float', - 'format', - 'frozenset', - 'getattr', - 'globals', - 'hasattr', - 'hash', - 'help', - 'hex', - 'id', - 'input', - 'int', - 'isinstance', - 'issubclass', - 'iter', - 'len', - 'list', - 'locals', - 'map', - 'max', - 'memoryview', - 'min', - 'next', - 'object', - 'oct', - 'open', - 'ord', - 'pow', - 'print', - 'property', - 'range', - 'repr', - 'reversed', - 'round', - 'set', - 'setattr', - 'slice', - 'sorted', - 'staticmethod', - 'str', - 'sum', - 'super', - 'tuple', - 'type', - 'vars', - 'zip' - ]; - - const LITERALS = [ - '__debug__', - 'Ellipsis', - 'False', - 'None', - 'NotImplemented', - 'True' - ]; - - // https://docs.python.org/3/library/typing.html - // TODO: Could these be supplemented by a CamelCase matcher in certain - // contexts, leaving these remaining only for relevance hinting? - const TYPES = [ - "Any", - "Callable", - "Coroutine", - "Dict", - "List", - "Literal", - "Generic", - "Optional", - "Sequence", - "Set", - "Tuple", - "Type", - "Union" - ]; - - const KEYWORDS = { - $pattern: /[A-Za-z]\w+|__\w+__/, - keyword: RESERVED_WORDS, - built_in: BUILT_INS, - literal: LITERALS, - type: TYPES - }; - - const PROMPT = { - className: 'meta', - begin: /^(>>>|\.\.\.) / - }; - - const SUBST = { - className: 'subst', - begin: /\{/, - end: /\}/, - keywords: KEYWORDS, - illegal: /#/ - }; - - const LITERAL_BRACKET = { - begin: /\{\{/, - relevance: 0 - }; - - const STRING = { - className: 'string', - contains: [ hljs.BACKSLASH_ESCAPE ], - variants: [ - { - begin: /([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/, - end: /'''/, - contains: [ - hljs.BACKSLASH_ESCAPE, - PROMPT - ], - relevance: 10 - }, - { - begin: /([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/, - end: /"""/, - contains: [ - hljs.BACKSLASH_ESCAPE, - PROMPT - ], - relevance: 10 - }, - { - begin: /([fF][rR]|[rR][fF]|[fF])'''/, - end: /'''/, - contains: [ - hljs.BACKSLASH_ESCAPE, - PROMPT, - LITERAL_BRACKET, - SUBST - ] - }, - { - begin: /([fF][rR]|[rR][fF]|[fF])"""/, - end: /"""/, - contains: [ - hljs.BACKSLASH_ESCAPE, - PROMPT, - LITERAL_BRACKET, - SUBST - ] - }, - { - begin: /([uU]|[rR])'/, - end: /'/, - relevance: 10 - }, - { - begin: /([uU]|[rR])"/, - end: /"/, - relevance: 10 - }, - { - begin: /([bB]|[bB][rR]|[rR][bB])'/, - end: /'/ - }, - { - begin: /([bB]|[bB][rR]|[rR][bB])"/, - end: /"/ - }, - { - begin: /([fF][rR]|[rR][fF]|[fF])'/, - end: /'/, - contains: [ - hljs.BACKSLASH_ESCAPE, - LITERAL_BRACKET, - SUBST - ] - }, - { - begin: /([fF][rR]|[rR][fF]|[fF])"/, - end: /"/, - contains: [ - hljs.BACKSLASH_ESCAPE, - LITERAL_BRACKET, - SUBST - ] - }, - hljs.APOS_STRING_MODE, - hljs.QUOTE_STRING_MODE - ] - }; - - // https://docs.python.org/3.9/reference/lexical_analysis.html#numeric-literals - const digitpart = '[0-9](_?[0-9])*'; - const pointfloat = `(\\b(${digitpart}))?\\.(${digitpart})|\\b(${digitpart})\\.`; - // Whitespace after a number (or any lexical token) is needed only if its absence - // would change the tokenization - // https://docs.python.org/3.9/reference/lexical_analysis.html#whitespace-between-tokens - // We deviate slightly, requiring a word boundary or a keyword - // to avoid accidentally recognizing *prefixes* (e.g., `0` in `0x41` or `08` or `0__1`) - const lookahead = `\\b|${RESERVED_WORDS.join('|')}`; - const NUMBER = { - className: 'number', - relevance: 0, - variants: [ - // exponentfloat, pointfloat - // https://docs.python.org/3.9/reference/lexical_analysis.html#floating-point-literals - // optionally imaginary - // https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals - // Note: no leading \b because floats can start with a decimal point - // and we don't want to mishandle e.g. `fn(.5)`, - // no trailing \b for pointfloat because it can end with a decimal point - // and we don't want to mishandle e.g. `0..hex()`; this should be safe - // because both MUST contain a decimal point and so cannot be confused with - // the interior part of an identifier - { - begin: `(\\b(${digitpart})|(${pointfloat}))[eE][+-]?(${digitpart})[jJ]?(?=${lookahead})` - }, - { - begin: `(${pointfloat})[jJ]?` - }, - - // decinteger, bininteger, octinteger, hexinteger - // https://docs.python.org/3.9/reference/lexical_analysis.html#integer-literals - // optionally "long" in Python 2 - // https://docs.python.org/2.7/reference/lexical_analysis.html#integer-and-long-integer-literals - // decinteger is optionally imaginary - // https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals - { - begin: `\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${lookahead})` - }, - { - begin: `\\b0[bB](_?[01])+[lL]?(?=${lookahead})` - }, - { - begin: `\\b0[oO](_?[0-7])+[lL]?(?=${lookahead})` - }, - { - begin: `\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${lookahead})` - }, - - // imagnumber (digitpart-based) - // https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals - { - begin: `\\b(${digitpart})[jJ](?=${lookahead})` - } - ] - }; - const COMMENT_TYPE = { - className: "comment", - begin: regex.lookahead(/# type:/), - end: /$/, - keywords: KEYWORDS, - contains: [ - { // prevent keywords from coloring `type` - begin: /# type:/ - }, - // comment within a datatype comment includes no keywords - { - begin: /#/, - end: /\b\B/, - endsWithParent: true - } - ] - }; - const PARAMS = { - className: 'params', - variants: [ - // Exclude params in functions without params - { - className: "", - begin: /\(\s*\)/, - skip: true - }, - { - begin: /\(/, - end: /\)/, - excludeBegin: true, - excludeEnd: true, - keywords: KEYWORDS, - contains: [ - 'self', - PROMPT, - NUMBER, - STRING, - hljs.HASH_COMMENT_MODE - ] - } - ] - }; - SUBST.contains = [ - STRING, - NUMBER, - PROMPT - ]; - - return { - name: 'Python', - aliases: [ - 'py', - 'gyp', - 'ipython' - ], - unicodeRegex: true, - keywords: KEYWORDS, - illegal: /(<\/|->|\?)|=>/, - contains: [ - PROMPT, - NUMBER, - { - // very common convention - begin: /\bself\b/ - }, - { - // eat "if" prior to string so that it won't accidentally be - // labeled as an f-string - beginKeywords: "if", - relevance: 0 - }, - STRING, - COMMENT_TYPE, - hljs.HASH_COMMENT_MODE, - { - match: [ - /\bdef/, /\s+/, - IDENT_RE, - ], - scope: { - 1: "keyword", - 3: "title.function" - }, - contains: [ PARAMS ] - }, - { - variants: [ - { - match: [ - /\bclass/, /\s+/, - IDENT_RE, /\s*/, - /\(\s*/, IDENT_RE,/\s*\)/ - ], - }, - { - match: [ - /\bclass/, /\s+/, - IDENT_RE - ], - } - ], - scope: { - 1: "keyword", - 3: "title.class", - 6: "title.class.inherited", - } - }, - { - className: 'meta', - begin: /^[\t ]*@/, - end: /(?=#)|$/, - contains: [ - NUMBER, - PARAMS, - STRING - ] - } - ] - }; -} - -var python_1 = python; - -// https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10 -var decimalDigits = '[0-9](_*[0-9])*'; -var frac = `\\.(${decimalDigits})`; -var hexDigits = '[0-9a-fA-F](_*[0-9a-fA-F])*'; -var NUMERIC = { - className: 'number', - variants: [ - // DecimalFloatingPointLiteral - // including ExponentPart - { begin: `(\\b(${decimalDigits})((${frac})|\\.)?|(${frac}))` + - `[eE][+-]?(${decimalDigits})[fFdD]?\\b` }, - // excluding ExponentPart - { begin: `\\b(${decimalDigits})((${frac})[fFdD]?\\b|\\.([fFdD]\\b)?)` }, - { begin: `(${frac})[fFdD]?\\b` }, - { begin: `\\b(${decimalDigits})[fFdD]\\b` }, - - // HexadecimalFloatingPointLiteral - { begin: `\\b0[xX]((${hexDigits})\\.?|(${hexDigits})?\\.(${hexDigits}))` + - `[pP][+-]?(${decimalDigits})[fFdD]?\\b` }, - - // DecimalIntegerLiteral - { begin: '\\b(0|[1-9](_*[0-9])*)[lL]?\\b' }, - - // HexIntegerLiteral - { begin: `\\b0[xX](${hexDigits})[lL]?\\b` }, - - // OctalIntegerLiteral - { begin: '\\b0(_*[0-7])*[lL]?\\b' }, - - // BinaryIntegerLiteral - { begin: '\\b0[bB][01](_*[01])*[lL]?\\b' }, - ], - relevance: 0 -}; - -/* -Language: Java -Author: Vsevolod Solovyov -Category: common, enterprise -Website: https://www.java.com/ -*/ - -/** - * Allows recursive regex expressions to a given depth - * - * ie: recurRegex("(abc~~~)", /~~~/g, 2) becomes: - * (abc(abc(abc))) - * - * @param {string} re - * @param {RegExp} substitution (should be a g mode regex) - * @param {number} depth - * @returns {string}`` - */ -function recurRegex(re, substitution, depth) { - if (depth === -1) return ""; - - return re.replace(substitution, _ => { - return recurRegex(re, substitution, depth - 1); - }); -} - -/** @type LanguageFn */ -function java(hljs) { - const regex = hljs.regex; - const JAVA_IDENT_RE = '[\u00C0-\u02B8a-zA-Z_$][\u00C0-\u02B8a-zA-Z_$0-9]*'; - const GENERIC_IDENT_RE = JAVA_IDENT_RE - + recurRegex('(?:<' + JAVA_IDENT_RE + '~~~(?:\\s*,\\s*' + JAVA_IDENT_RE + '~~~)*>)?', /~~~/g, 2); - const MAIN_KEYWORDS = [ - 'synchronized', - 'abstract', - 'private', - 'var', - 'static', - 'if', - 'const ', - 'for', - 'while', - 'strictfp', - 'finally', - 'protected', - 'import', - 'native', - 'final', - 'void', - 'enum', - 'else', - 'break', - 'transient', - 'catch', - 'instanceof', - 'volatile', - 'case', - 'assert', - 'package', - 'default', - 'public', - 'try', - 'switch', - 'continue', - 'throws', - 'protected', - 'public', - 'private', - 'module', - 'requires', - 'exports', - 'do', - 'sealed' - ]; - - const BUILT_INS = [ - 'super', - 'this' - ]; - - const LITERALS = [ - 'false', - 'true', - 'null' - ]; - - const TYPES = [ - 'char', - 'boolean', - 'long', - 'float', - 'int', - 'byte', - 'short', - 'double' - ]; - - const KEYWORDS = { - keyword: MAIN_KEYWORDS, - literal: LITERALS, - type: TYPES, - built_in: BUILT_INS - }; - - const ANNOTATION = { - className: 'meta', - begin: '@' + JAVA_IDENT_RE, - contains: [ - { - begin: /\(/, - end: /\)/, - contains: [ "self" ] // allow nested () inside our annotation - } - ] - }; - const PARAMS = { - className: 'params', - begin: /\(/, - end: /\)/, - keywords: KEYWORDS, - relevance: 0, - contains: [ hljs.C_BLOCK_COMMENT_MODE ], - endsParent: true - }; - - return { - name: 'Java', - aliases: [ 'jsp' ], - keywords: KEYWORDS, - illegal: /<\/|#/, - contains: [ - hljs.COMMENT( - '/\\*\\*', - '\\*/', - { - relevance: 0, - contains: [ - { - // eat up @'s in emails to prevent them to be recognized as doctags - begin: /\w+@/, - relevance: 0 - }, - { - className: 'doctag', - begin: '@[A-Za-z]+' - } - ] - } - ), - // relevance boost - { - begin: /import java\.[a-z]+\./, - keywords: "import", - relevance: 2 - }, - hljs.C_LINE_COMMENT_MODE, - hljs.C_BLOCK_COMMENT_MODE, - { - begin: /"""/, - end: /"""/, - className: "string", - contains: [ hljs.BACKSLASH_ESCAPE ] - }, - hljs.APOS_STRING_MODE, - hljs.QUOTE_STRING_MODE, - { - match: [ - /\b(?:class|interface|enum|extends|implements|new)/, - /\s+/, - JAVA_IDENT_RE - ], - className: { - 1: "keyword", - 3: "title.class" - } - }, - { - // Exceptions for hyphenated keywords - match: /non-sealed/, - scope: "keyword" - }, - { - begin: [ - regex.concat(/(?!else)/, JAVA_IDENT_RE), - /\s+/, - JAVA_IDENT_RE, - /\s+/, - /=/ - ], - className: { - 1: "type", - 3: "variable", - 5: "operator" - } - }, - { - begin: [ - /record/, - /\s+/, - JAVA_IDENT_RE - ], - className: { - 1: "keyword", - 3: "title.class" - }, - contains: [ - PARAMS, - hljs.C_LINE_COMMENT_MODE, - hljs.C_BLOCK_COMMENT_MODE - ] - }, - { - // Expression keywords prevent 'keyword Name(...)' from being - // recognized as a function definition - beginKeywords: 'new throw return else', - relevance: 0 - }, - { - begin: [ - '(?:' + GENERIC_IDENT_RE + '\\s+)', - hljs.UNDERSCORE_IDENT_RE, - /\s*(?=\()/ - ], - className: { 2: "title.function" }, - keywords: KEYWORDS, - contains: [ - { - className: 'params', - begin: /\(/, - end: /\)/, - keywords: KEYWORDS, - relevance: 0, - contains: [ - ANNOTATION, - hljs.APOS_STRING_MODE, - hljs.QUOTE_STRING_MODE, - NUMERIC, - hljs.C_BLOCK_COMMENT_MODE - ] - }, - hljs.C_LINE_COMMENT_MODE, - hljs.C_BLOCK_COMMENT_MODE - ] - }, - NUMERIC, - ANNOTATION - ] - }; -} - -var java_1 = java; - -/* - Language: SQL - Website: https://en.wikipedia.org/wiki/SQL - Category: common, database - */ -/* - -Goals: - -SQL is intended to highlight basic/common SQL keywords and expressions - -- If pretty much every single SQL server includes supports, then it's a canidate. -- It is NOT intended to include tons of vendor specific keywords (Oracle, MySQL, - PostgreSQL) although the list of data types is purposely a bit more expansive. -- For more specific SQL grammars please see: - - PostgreSQL and PL/pgSQL - core - - T-SQL - https://github.com/highlightjs/highlightjs-tsql - - sql_more (core) - - */ - -function sql(hljs) { - const regex = hljs.regex; - const COMMENT_MODE = hljs.COMMENT('--', '$'); - const STRING = { - className: 'string', - variants: [ - { - begin: /'/, - end: /'/, - contains: [ { begin: /''/ } ] - } - ] - }; - const QUOTED_IDENTIFIER = { - begin: /"/, - end: /"/, - contains: [ { begin: /""/ } ] - }; - - const LITERALS = [ - "true", - "false", - // Not sure it's correct to call NULL literal, and clauses like IS [NOT] NULL look strange that way. - // "null", - "unknown" - ]; - - const MULTI_WORD_TYPES = [ - "double precision", - "large object", - "with timezone", - "without timezone" - ]; - - const TYPES = [ - 'bigint', - 'binary', - 'blob', - 'boolean', - 'char', - 'character', - 'clob', - 'date', - 'dec', - 'decfloat', - 'decimal', - 'float', - 'int', - 'integer', - 'interval', - 'nchar', - 'nclob', - 'national', - 'numeric', - 'real', - 'row', - 'smallint', - 'time', - 'timestamp', - 'varchar', - 'varying', // modifier (character varying) - 'varbinary' - ]; - - const NON_RESERVED_WORDS = [ - "add", - "asc", - "collation", - "desc", - "final", - "first", - "last", - "view" - ]; - - // https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#reserved-word - const RESERVED_WORDS = [ - "abs", - "acos", - "all", - "allocate", - "alter", - "and", - "any", - "are", - "array", - "array_agg", - "array_max_cardinality", - "as", - "asensitive", - "asin", - "asymmetric", - "at", - "atan", - "atomic", - "authorization", - "avg", - "begin", - "begin_frame", - "begin_partition", - "between", - "bigint", - "binary", - "blob", - "boolean", - "both", - "by", - "call", - "called", - "cardinality", - "cascaded", - "case", - "cast", - "ceil", - "ceiling", - "char", - "char_length", - "character", - "character_length", - "check", - "classifier", - "clob", - "close", - "coalesce", - "collate", - "collect", - "column", - "commit", - "condition", - "connect", - "constraint", - "contains", - "convert", - "copy", - "corr", - "corresponding", - "cos", - "cosh", - "count", - "covar_pop", - "covar_samp", - "create", - "cross", - "cube", - "cume_dist", - "current", - "current_catalog", - "current_date", - "current_default_transform_group", - "current_path", - "current_role", - "current_row", - "current_schema", - "current_time", - "current_timestamp", - "current_path", - "current_role", - "current_transform_group_for_type", - "current_user", - "cursor", - "cycle", - "date", - "day", - "deallocate", - "dec", - "decimal", - "decfloat", - "declare", - "default", - "define", - "delete", - "dense_rank", - "deref", - "describe", - "deterministic", - "disconnect", - "distinct", - "double", - "drop", - "dynamic", - "each", - "element", - "else", - "empty", - "end", - "end_frame", - "end_partition", - "end-exec", - "equals", - "escape", - "every", - "except", - "exec", - "execute", - "exists", - "exp", - "external", - "extract", - "false", - "fetch", - "filter", - "first_value", - "float", - "floor", - "for", - "foreign", - "frame_row", - "free", - "from", - "full", - "function", - "fusion", - "get", - "global", - "grant", - "group", - "grouping", - "groups", - "having", - "hold", - "hour", - "identity", - "in", - "indicator", - "initial", - "inner", - "inout", - "insensitive", - "insert", - "int", - "integer", - "intersect", - "intersection", - "interval", - "into", - "is", - "join", - "json_array", - "json_arrayagg", - "json_exists", - "json_object", - "json_objectagg", - "json_query", - "json_table", - "json_table_primitive", - "json_value", - "lag", - "language", - "large", - "last_value", - "lateral", - "lead", - "leading", - "left", - "like", - "like_regex", - "listagg", - "ln", - "local", - "localtime", - "localtimestamp", - "log", - "log10", - "lower", - "match", - "match_number", - "match_recognize", - "matches", - "max", - "member", - "merge", - "method", - "min", - "minute", - "mod", - "modifies", - "module", - "month", - "multiset", - "national", - "natural", - "nchar", - "nclob", - "new", - "no", - "none", - "normalize", - "not", - "nth_value", - "ntile", - "null", - "nullif", - "numeric", - "octet_length", - "occurrences_regex", - "of", - "offset", - "old", - "omit", - "on", - "one", - "only", - "open", - "or", - "order", - "out", - "outer", - "over", - "overlaps", - "overlay", - "parameter", - "partition", - "pattern", - "per", - "percent", - "percent_rank", - "percentile_cont", - "percentile_disc", - "period", - "portion", - "position", - "position_regex", - "power", - "precedes", - "precision", - "prepare", - "primary", - "procedure", - "ptf", - "range", - "rank", - "reads", - "real", - "recursive", - "ref", - "references", - "referencing", - "regr_avgx", - "regr_avgy", - "regr_count", - "regr_intercept", - "regr_r2", - "regr_slope", - "regr_sxx", - "regr_sxy", - "regr_syy", - "release", - "result", - "return", - "returns", - "revoke", - "right", - "rollback", - "rollup", - "row", - "row_number", - "rows", - "running", - "savepoint", - "scope", - "scroll", - "search", - "second", - "seek", - "select", - "sensitive", - "session_user", - "set", - "show", - "similar", - "sin", - "sinh", - "skip", - "smallint", - "some", - "specific", - "specifictype", - "sql", - "sqlexception", - "sqlstate", - "sqlwarning", - "sqrt", - "start", - "static", - "stddev_pop", - "stddev_samp", - "submultiset", - "subset", - "substring", - "substring_regex", - "succeeds", - "sum", - "symmetric", - "system", - "system_time", - "system_user", - "table", - "tablesample", - "tan", - "tanh", - "then", - "time", - "timestamp", - "timezone_hour", - "timezone_minute", - "to", - "trailing", - "translate", - "translate_regex", - "translation", - "treat", - "trigger", - "trim", - "trim_array", - "true", - "truncate", - "uescape", - "union", - "unique", - "unknown", - "unnest", - "update", - "upper", - "user", - "using", - "value", - "values", - "value_of", - "var_pop", - "var_samp", - "varbinary", - "varchar", - "varying", - "versioning", - "when", - "whenever", - "where", - "width_bucket", - "window", - "with", - "within", - "without", - "year", - ]; - - // these are reserved words we have identified to be functions - // and should only be highlighted in a dispatch-like context - // ie, array_agg(...), etc. - const RESERVED_FUNCTIONS = [ - "abs", - "acos", - "array_agg", - "asin", - "atan", - "avg", - "cast", - "ceil", - "ceiling", - "coalesce", - "corr", - "cos", - "cosh", - "count", - "covar_pop", - "covar_samp", - "cume_dist", - "dense_rank", - "deref", - "element", - "exp", - "extract", - "first_value", - "floor", - "json_array", - "json_arrayagg", - "json_exists", - "json_object", - "json_objectagg", - "json_query", - "json_table", - "json_table_primitive", - "json_value", - "lag", - "last_value", - "lead", - "listagg", - "ln", - "log", - "log10", - "lower", - "max", - "min", - "mod", - "nth_value", - "ntile", - "nullif", - "percent_rank", - "percentile_cont", - "percentile_disc", - "position", - "position_regex", - "power", - "rank", - "regr_avgx", - "regr_avgy", - "regr_count", - "regr_intercept", - "regr_r2", - "regr_slope", - "regr_sxx", - "regr_sxy", - "regr_syy", - "row_number", - "sin", - "sinh", - "sqrt", - "stddev_pop", - "stddev_samp", - "substring", - "substring_regex", - "sum", - "tan", - "tanh", - "translate", - "translate_regex", - "treat", - "trim", - "trim_array", - "unnest", - "upper", - "value_of", - "var_pop", - "var_samp", - "width_bucket", - ]; - - // these functions can - const POSSIBLE_WITHOUT_PARENS = [ - "current_catalog", - "current_date", - "current_default_transform_group", - "current_path", - "current_role", - "current_schema", - "current_transform_group_for_type", - "current_user", - "session_user", - "system_time", - "system_user", - "current_time", - "localtime", - "current_timestamp", - "localtimestamp" - ]; - - // those exist to boost relevance making these very - // "SQL like" keyword combos worth +1 extra relevance - const COMBOS = [ - "create table", - "insert into", - "primary key", - "foreign key", - "not null", - "alter table", - "add constraint", - "grouping sets", - "on overflow", - "character set", - "respect nulls", - "ignore nulls", - "nulls first", - "nulls last", - "depth first", - "breadth first" - ]; - - const FUNCTIONS = RESERVED_FUNCTIONS; - - const KEYWORDS = [ - ...RESERVED_WORDS, - ...NON_RESERVED_WORDS - ].filter((keyword) => { - return !RESERVED_FUNCTIONS.includes(keyword); - }); - - const VARIABLE = { - className: "variable", - begin: /@[a-z0-9]+/, - }; - - const OPERATOR = { - className: "operator", - begin: /[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/, - relevance: 0, - }; - - const FUNCTION_CALL = { - begin: regex.concat(/\b/, regex.either(...FUNCTIONS), /\s*\(/), - relevance: 0, - keywords: { built_in: FUNCTIONS } - }; - - // keywords with less than 3 letters are reduced in relevancy - function reduceRelevancy(list, { - exceptions, when - } = {}) { - const qualifyFn = when; - exceptions = exceptions || []; - return list.map((item) => { - if (item.match(/\|\d+$/) || exceptions.includes(item)) { - return item; - } else if (qualifyFn(item)) { - return `${item}|0`; - } else { - return item; - } - }); - } - - return { - name: 'SQL', - case_insensitive: true, - // does not include {} or HTML tags ` x.length < 3 }), - literal: LITERALS, - type: TYPES, - built_in: POSSIBLE_WITHOUT_PARENS - }, - contains: [ - { - begin: regex.either(...COMBOS), - relevance: 0, - keywords: { - $pattern: /[\w\.]+/, - keyword: KEYWORDS.concat(COMBOS), - literal: LITERALS, - type: TYPES - }, - }, - { - className: "type", - begin: regex.either(...MULTI_WORD_TYPES) - }, - FUNCTION_CALL, - VARIABLE, - STRING, - QUOTED_IDENTIFIER, - hljs.C_NUMBER_MODE, - hljs.C_BLOCK_COMMENT_MODE, - COMMENT_MODE, - OPERATOR - ] - }; -} - -var sql_1 = sql; - -/* -Language: HTML, XML -Website: https://www.w3.org/XML/ -Category: common, web -Audit: 2020 -*/ -/** @type LanguageFn */ -function xml(hljs) { - const regex = hljs.regex; - // Element names can contain letters, digits, hyphens, underscores, and periods - const TAG_NAME_RE = regex.concat(/[A-Z_]/, regex.optional(/[A-Z0-9_.-]*:/), /[A-Z0-9_.-]*/); - const XML_IDENT_RE = /[A-Za-z0-9._:-]+/; - const XML_ENTITIES = { - className: 'symbol', - begin: /&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/ - }; - const XML_META_KEYWORDS = { - begin: /\s/, - contains: [ - { - className: 'keyword', - begin: /#?[a-z_][a-z1-9_-]+/, - illegal: /\n/ - } - ] - }; - const XML_META_PAR_KEYWORDS = hljs.inherit(XML_META_KEYWORDS, { - begin: /\(/, - end: /\)/ - }); - const APOS_META_STRING_MODE = hljs.inherit(hljs.APOS_STRING_MODE, { className: 'string' }); - const QUOTE_META_STRING_MODE = hljs.inherit(hljs.QUOTE_STRING_MODE, { className: 'string' }); - const TAG_INTERNALS = { - endsWithParent: true, - illegal: /`]+/ } - ] - } - ] - } - ] - }; - return { - name: 'HTML, XML', - aliases: [ - 'html', - 'xhtml', - 'rss', - 'atom', - 'xjb', - 'xsd', - 'xsl', - 'plist', - 'wsf', - 'svg' - ], - case_insensitive: true, - contains: [ - { - className: 'meta', - begin: //, - relevance: 10, - contains: [ - XML_META_KEYWORDS, - QUOTE_META_STRING_MODE, - APOS_META_STRING_MODE, - XML_META_PAR_KEYWORDS, - { - begin: /\[/, - end: /\]/, - contains: [ - { - className: 'meta', - begin: //, - contains: [ - XML_META_KEYWORDS, - XML_META_PAR_KEYWORDS, - QUOTE_META_STRING_MODE, - APOS_META_STRING_MODE - ] - } - ] - } - ] - }, - hljs.COMMENT( - //, - { relevance: 10 } - ), - { - begin: //, - relevance: 10 - }, - XML_ENTITIES, - // xml processing instructions - { - className: 'meta', - end: /\?>/, - variants: [ - { - begin: /<\?xml/, - relevance: 10, - contains: [ - QUOTE_META_STRING_MODE - ] - }, - { - begin: /<\?[a-z][a-z0-9]+/, - } - ] - - }, - { - className: 'tag', - /* - The lookahead pattern (?=...) ensures that 'begin' only matches - ')/, - end: />/, - keywords: { name: 'style' }, - contains: [ TAG_INTERNALS ], - starts: { - end: /<\/style>/, - returnEnd: true, - subLanguage: [ - 'css', - 'xml' - ] - } - }, - { - className: 'tag', - // See the comment in the