{ "version": 3, "sources": ["../themes/workstringsinternational.com/js/$.js", "../themes/workstringsinternational.com/modules/site-header/default/index.js", "../themes/workstringsinternational.com/modules/two-column/default/index.js", "../themes/workstringsinternational.com/modules/cta/2-col/index.js", "../themes/workstringsinternational.com/modules/page-header/home/index.js", "../themes/workstringsinternational.com/modules/page-list/filter-grid/index.js", "../themes/workstringsinternational.com/modules/map/default/styles.json", "../themes/workstringsinternational.com/modules/map/default/index.js", "../node_modules/simple-datatables/src/helpers.ts", "../node_modules/simple-datatables/node_modules/diff-dom/dist/module.js", "../node_modules/simple-datatables/src/virtual_dom.ts", "../node_modules/simple-datatables/node_modules/dayjs/dayjs.min.js", "../node_modules/simple-datatables/node_modules/dayjs/plugin/customParseFormat.js", "../node_modules/simple-datatables/src/date.ts", "../node_modules/simple-datatables/src/read_data.ts", "../node_modules/simple-datatables/src/rows.ts", "../node_modules/simple-datatables/src/columns.ts", "../node_modules/simple-datatables/src/column_settings.ts", "../node_modules/simple-datatables/src/templates.ts", "../node_modules/simple-datatables/src/config.ts", "../node_modules/simple-datatables/src/virtual_pager_dom.ts", "../node_modules/simple-datatables/src/datatable.ts", "../node_modules/simple-datatables/src/convert/csv.ts", "../node_modules/simple-datatables/src/convert/json.ts", "../node_modules/simple-datatables/src/export/csv.ts", "../node_modules/simple-datatables/src/export/json.ts", "../node_modules/simple-datatables/src/export/sql.ts", "../node_modules/simple-datatables/src/export/txt.ts", "../node_modules/simple-datatables/src/editing/config.ts", "../node_modules/simple-datatables/src/editing/editor.ts", "../node_modules/simple-datatables/src/column_filter/config.ts", "../node_modules/simple-datatables/src/column_filter/column_filter.ts", "../themes/workstringsinternational.com/modules/table/spec-sheets/columns.json", "../node_modules/@brandextract-dev/workstrings-data/lib/pdf-constants.js", "../node_modules/big.js/big.mjs", "../node_modules/@brandextract-dev/workstrings-data/lib/normalize.js", "../node_modules/fraction.js/dist/fraction.mjs", "../themes/workstringsinternational.com/modules/table/spec-sheets/index.js", "../themes/workstringsinternational.com/modules/contact-form/default/index.js", "../node_modules/gsap/gsap-core.js", "../node_modules/gsap/CSSPlugin.js", "../node_modules/gsap/index.js", "../themes/workstringsinternational.com/modules/timeline/default/index.js", "../themes/workstringsinternational.com/modules/article/default/index.js", "../themes/workstringsinternational.com/modules/search/Google-CSE/index.js", "../node_modules/gsap/Observer.js", "../node_modules/gsap/ScrollTrigger.js", "../themes/workstringsinternational.com/js/observers.js", "../themes/workstringsinternational.com/js/dialog.js", "../themes/workstringsinternational.com/js/index.js"], "sourcesContent": ["/**\n * Queries for a single element with selector\n * @param {string} selector\n * @param {Document|Element} [parent=document]\n * @returns {Element}\n */\nglobalThis.$ = (selector, parent = document) => parent.querySelector(selector);\n\n/**\n * Queries for a node list with selector\n * @param {string} selector\n * @param {Document|Element} [parent=document]\n * @returns {NodeList}\n */\nglobalThis.$$ = (selector, parent = document) =>\n parent.querySelectorAll(selector);\n", "const $ = (selector, parent = document) => parent.querySelector(selector);\nconst $$ = (selector, parent = document) => parent.querySelectorAll(selector);\n\nconst mobileMenu = $(\"header[role='banner'].site-header\");\n\nfunction throttle(fn, wait) {\n let time = Date.now();\n return function() {\n if ((time + wait - Date.now()) < 0) {\n fn();\n time = Date.now();\n }\n }\n}\n\nfunction toggleMobileMenu() {\n const button = $(`.site-header [aria-controls=\"primary-nav\"]`);\n const state = button.getAttribute(\"aria-expanded\");\n const isOpen = state === \"true\";\n const mobileMenu = $(\"header[role='banner'].site-header\");\n\n button.setAttribute(\"aria-expanded\", isOpen ? \"false\" : \"true\");\n button.innerText = isOpen ? \"Menu\" : \"Close\";\n mobileMenu.classList.toggle(\"menu-open\");\n $(\"body\").classList.toggle(\"overflow-hidden\");\n}\n\nfunction openSubnav(parent) {\n const button = $(\"button\", parent);\n\n parent?.classList.add(\"open\");\n button?.setAttribute(`aria-expanded`, `true`);\n}\n\nfunction closeSubnav(parent) {\n const button = $(\"button\", parent);\n\n parent?.classList.remove(\"open\");\n button?.setAttribute(`aria-expanded`, `false`);\n}\n\nfunction closeSubnavs() {\n const openMenus = $$(\".site-header .isParent.open, .site-header .isGrandParent.open\");\n openMenus.forEach(function(menu) {\n closeSubnav(menu);\n })\n}\n\n// $(\".search-toggle\").addEventListener(\"click\", function(event) {\n// $(\"header nav[aria-label='Utility'] form[role='search'] input.search-field\").focus();\n// });\n\ndocument.addEventListener(\"click\", function(event) {\n const button = event.target.closest(`.site-header [aria-controls=\"primary-nav\"]`);\n if (!button) {\n return;\n }\n\n toggleMobileMenu();\n});\n\ndocument.addEventListener('touchend', function (event) {\n let closest = event.target.closest(\".site-header:not(.menu-open) .isParent > a, .site-header:not(.menu-open) .isGrandParent > a\");\n if ($(\".site-header.menu-open\")) {\n return;\n }\n \n if (closest) {\n let parent = closest.parentNode;\n if (parent.classList.contains(\"open\")) return;\n closeSubnavs();\n openSubnav(parent);\n } else {\n const inMenu = event.target.closest(\"li.open\");\n if (!inMenu) {\n closeSubnavs();\n }\n return;\n }\n event.preventDefault();\n}, false);\n\ndocument.addEventListener('mouseover', function (event) {\n let closest = event.target.closest(\".site-header:not(.menu-open) nav#primary-nav > ul > .isParent, .site-header:not(.menu-open) nav#primary-nav > ul > .isGrandParent\");\n if (!closest) return;\n openSubnav(closest);\n}, false);\n\ndocument.addEventListener('mouseout', function (event) {\n let closest = event.target.closest(\".site-header:not(.menu-open) nav#primary-nav > ul > .isParent, .site-header:not(.menu-open) nav#primary-nav > ul > .isGrandParent\");\n if (!closest) return;\n closeSubnav(closest);\n}, false);\n\ndocument.addEventListener('click', function (event) {\n let closest = event.target.closest(\".site-header:not(.menu-open) #primary-nav a + button\");\n if (!closest) return;\n\n let $toggle = closest;\n let $navItem = $toggle.closest(`li`);\n let $otherNavItems = Array.prototype.filter.call($navItem.parentNode.children, function(child){\n return child !== $navItem;\n });\n\n $otherNavItems.forEach(item => {\n closeSubnav(item);\n })\n\n if ($navItem.classList.contains(\"open\")) {\n closeSubnav($navItem);\n } else {\n openSubnav($navItem);\n }\n}, false);\n\ndocument.addEventListener('click', function (event) {\n const targets = `\n .site-header.menu-open #primary-nav > ul > .isParent > a,\n .site-header.menu-open #primary-nav > ul > .isParent > button,\n .site-header.menu-open #primary-nav > ul > .isGrandParent > a,\n .site-header.menu-open #primary-nav > ul > .isGrandParent > button\n `\n const closest = event.target.closest(targets);\n if (!closest) return;\n\n const $navItem = closest.parentNode;\n let siblings = Array.prototype.filter.call($navItem.parentNode.children, function(child){\n return child !== $navItem;\n });\n\n event.preventDefault();\n\n if ($navItem.classList.contains(`open`)) {\n closeSubnav($navItem);\n $(\".site-header\").classList.remove(\"submenu-open\");\n } else {\n openSubnav($navItem);\n siblings.forEach(sibling => {\n closeSubnav(sibling);\n })\n $(\".site-header\").classList.add(\"submenu-open\");\n }\n}, false);\n\n// header class on hover\nconst header = document.querySelector('header.site-header');\n\nheader.addEventListener('mouseover', () => {\n header.classList.add('hovered');\n});\nheader.addEventListener('mouseout', () => {\n header.classList.remove('hovered');\n});\n\nlet lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;\n\nlet scrollCallback = function(){\n let scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n let diff = Math.abs(lastScrollTop - scrollTop);\n\n if (!header.classList.contains(\"menu-open\")) {\n if (scrollTop > lastScrollTop){\n if (header.classList.contains(\"unfold\") && diff > 10) {\n header.classList.remove(\"unfold\");\n }\n } else {\n if (!header.classList.contains(\"unfold\") && diff > 10 && document.documentElement.scrollTop > 500) {\n const headerHeight = header.offsetHeight;\n header.classList.add(\"unfold\");\n } else if (header.classList.contains(\"unfold\") && document.documentElement.scrollTop <= 500) {\n header.classList.remove(\"unfold\");\n }\n }\n }\n\n if (diff > 10) {\n lastScrollTop = scrollTop<= 0 ? 0 : scrollTop; // For Mobile or negative scrolling\n }\n}\n\nwindow.addEventListener(\"scroll\", throttle(scrollCallback, 25) , false);", "const $ = (selector, parent = document) => parent.querySelector(selector);\nconst $$ = (selector, parent = document) => parent.querySelectorAll(selector);\n\nconst columnSections = $$(\".two-column-default\");\n\ncolumnSections.forEach(function(section) {\n const columns = $$(\".column:nth-child(even)\", section);\n\n columns.forEach(function(column) {\n if ($(\"p:first-child:last-child img:first-child:last-child\", column)) {\n const previousSibling = column.previousElementSibling;\n const previousPosition = getComputedStyle(previousSibling).getPropertyValue(\"--position\");\n const currentPosition = getComputedStyle(column).getPropertyValue(\"--position\");\n\n column.style.setProperty(\"--mobile-position\", previousPosition);\n previousSibling.style.setProperty(\"--mobile-position\", currentPosition);\n previousSibling.classList.add(\"flipped\");\n }\n });\n});", "const $ = (selector, parent = document) => parent.querySelector(selector);\nconst $$ = (selector, parent = document) => parent.querySelectorAll(selector);\n\nconst observer = new IntersectionObserver(entries => {\n entries.forEach(entry => {\n if (entry.intersectionRatio > 0) {\n entry.target.classList.add('animate');\n }\n else {\n entry.target.classList.remove('animate');\n }\n })\n})\nconst boxElList = $$(\".cta-2-col\");\nboxElList.forEach((el) => {\n observer.observe(el);\n})", "const $ = (selector, parent = document) => parent.querySelector(selector);\nconst $$ = (selector, parent = document) => parent.querySelectorAll(selector);\n\nconst imageSwapper = $(\".page-header-home .image-swapper\");\n\nif (imageSwapper) {\n const items = $$(\"li\", imageSwapper);\n let currentItem = 0;\n\n function swapImage() {\n items[currentItem].classList.remove(\"active\");\n currentItem = (currentItem + 1) % items.length;\n items[currentItem].classList.add(\"active\");\n }\n\n setInterval(swapImage, 5000);\n}", "const $ = (selector, parent = document) => parent.querySelector(selector);\nconst $$ = (selector, parent = document) => parent.querySelectorAll(selector);\n\nconst itemsPerPage = 6;\nlet currentPage = 1;\n\nconst pagination = $(\".pagination\");\n\n$$(\".filter-grid\").forEach(function(filterGrid) {\n const filters = $(\".filters\", filterGrid);\n const items = $$(\"ul.grid li\", filterGrid);\n const grid = $(\"ul.grid\", filterGrid);\n \n\n if (filters) {\n const categories = filters.dataset.categories.split(\",\");\n\n categories.forEach(function(category) {\n const label = document.createElement(\"label\");\n const input = document.createElement(\"input\");\n input.type = \"radio\";\n input.classList.add(\"sr-only\");\n input.name = \"category\";\n input.value = category;\n const span = document.createElement(\"span\");\n span.textContent = category;\n label.appendChild(input);\n label.appendChild(span);\n filters.appendChild(label);\n });\n \n const filterInputs = $$(\"input\", filters);\n filterInputs.forEach(function(input) {\n input.addEventListener(\"change\", function() {\n currentPage = 1;\n const category = this.value;\n items.forEach(function(item) {\n if (category === \"all\") {\n item.classList.remove(\"filtered\");\n } else if (item.dataset.category === category) {\n item.classList.remove(\"filtered\");\n } else {\n item.classList.add(\"filtered\");\n }\n });\n \n $$(\"li:not(.filtered)\", grid).forEach(function(item, index) {\n if (index >= itemsPerPage) {\n item.classList.add(\"hidden\");\n } else {\n item.classList.remove(\"hidden\");\n } \n });\n \n initLoadMore();\n initPagination();\n });\n });\n }\n});\n\nfunction initLoadMore() {\n $$(\".grid-load-more\").forEach(function(loadMoreSection) {\n const hiddenItems = $$(\"li.hidden:not(.filtered)\", loadMoreSection);\n const loadMoreButton = $(\".load-more\", loadMoreSection);\n\n if (!loadMoreButton) {\n return;\n }\n\n if (hiddenItems.length > 0) {\n loadMoreButton.classList.remove(\"hidden\");\n } else {\n loadMoreButton.classList.add(\"hidden\");\n }\n });\n}\n\nfunction initPagination() {\n const pagination = $(\".pagination\");\n const paginationList = $(\".pagination ul\");\n if (!pagination) {\n return;\n }\n\n const itemsNotFiltered = $$(\".grid-load-more .grid li:not(.filtered)\");\n\n if (itemsNotFiltered.length > itemsPerPage) {\n paginationList.innerHTML = \"\";\n\n const pages = Math.floor(itemsNotFiltered.length / itemsPerPage);\n \n if (pages === 1) {\n pagination.classList.add(\"invisible\");\n pagination.classList.add(\"hidden\");\n return;\n }\n\n const previous = document.createElement(\"li\");\n previous.classList.add(\"previous\");\n previous.innerHTML = ``;\n\n //create next button item\n const next = document.createElement(\"li\");\n next.classList.add(\"next\");\n next.innerHTML = ``;\n\n const createPageButton = (pageNumber) => {\n const page = document.createElement(\"li\");\n if (currentPage === pageNumber) {\n page.classList.add(\"active\");\n }\n page.innerHTML = ``;\n return page;\n };\n\n const createEllipsis = () => {\n const ellipsis = document.createElement(\"li\");\n ellipsis.classList.add(\"ellipsis\");\n ellipsis.innerHTML = `...`;\n return ellipsis;\n };\n\n const renderPagination = (currentPage) => {\n paginationList.innerHTML = \"\";\n paginationList.appendChild(previous);\n\n if (pages <= 5) {\n for (let i = 1; i <= pages; i++) {\n paginationList.appendChild(createPageButton(i));\n }\n } else {\n if (currentPage > 4) {\n paginationList.appendChild(createPageButton(1));\n paginationList.appendChild(createPageButton(2));\n paginationList.appendChild(createEllipsis());\n } else {\n for (let i = 1; i <= currentPage - 2; i++) {\n paginationList.appendChild(createPageButton(i));\n }\n }\n\n let startPage = Math.max(1, currentPage - 1);\n let endPage = Math.min(pages, currentPage + 1);\n\n for (let i = startPage; i <= endPage; i++) {\n paginationList.appendChild(createPageButton(i));\n }\n\n if (currentPage < pages - 3) {\n paginationList.appendChild(createEllipsis());\n paginationList.appendChild(createPageButton(pages-1));\n paginationList.appendChild(createPageButton(pages));\n } else if (currentPage + 2 <= pages) {\n for (let i = currentPage + 2; i <= pages; i++) {\n paginationList.appendChild(createPageButton(i));\n }\n }\n }\n\n paginationList.appendChild(next);\n };\n\n renderPagination(currentPage);\n pagination.classList.remove(\"invisible\");\n pagination.classList.remove(\"hidden\");\n }\n}\n\n$(\".grid-load-more .load-more\")?.addEventListener(\"click\", function() {\n const loadMoreSection = this.closest(\".grid-load-more\");\n const hiddenItems = $$(\"li.hidden:not(.filtered)\", loadMoreSection);\n const loadMoreButton = $(\".load-more\", loadMoreSection);\n\n hiddenItems.forEach(function(item, index) {\n if (index < itemsPerPage) {\n item.classList.remove(\"hidden\");\n }\n });\n\n if (hiddenItems.length <= itemsPerPage) {\n loadMoreButton.classList.add(\"hidden\");\n }\n});\n\n\nif (pagination) {\n document.addEventListener(\"click\", function(event) {\n const closest = event.target.closest(\".pagination button\");\n if (!closest) {\n return;\n }\n\n const itemsNotFiltered = $$(\".grid-load-more li:not(.filtered)\");\n const pages = Math.floor(itemsNotFiltered.length / itemsPerPage);\n const page = closest.textContent;\n\n if (page.indexOf(\"<\") > -1) {\n currentPage = Math.max(1, currentPage - 1);\n } else if (page.indexOf(\">\") > -1) {\n currentPage = Math.min(pages, currentPage + 1);\n } else {\n currentPage = parseInt(page);\n }\n\n itemsNotFiltered.forEach(function(item, index) {\n if (index < itemsPerPage * (currentPage - 1) || index >= itemsPerPage * currentPage) {\n item.classList.add(\"hidden\");\n } else {\n item.classList.remove(\"hidden\");\n }\n });\n\n //scroll to section\n const section = $(\".grid-load-more\");\n const offset = section.getBoundingClientRect().top + window.scrollY - 100;\n window.scrollTo({\n top: offset,\n behavior: \"smooth\"\n });\n initPagination();\n });\n}\n\n\ninitLoadMore();\ninitPagination();", "[\n {\n \"featureType\": \"landscape\",\n \"elementType\": \"labels\",\n \"stylers\": [\n {\n \"visibility\": \"off\"\n }\n ]\n },\n {\n \"featureType\": \"transit\",\n \"elementType\": \"labels\",\n \"stylers\": [\n {\n \"visibility\": \"off\"\n }\n ]\n },\n {\n \"featureType\": \"poi\",\n \"elementType\": \"labels\",\n \"stylers\": [\n {\n \"visibility\": \"off\"\n }\n ]\n },\n {\n \"featureType\": \"water\",\n \"elementType\": \"labels\",\n \"stylers\": [\n {\n \"visibility\": \"off\"\n }\n ]\n },\n {\n \"featureType\": \"road\",\n \"elementType\": \"labels.icon\",\n \"stylers\": [\n {\n \"visibility\": \"off\"\n }\n ]\n },\n {\n \"stylers\": [\n {\n \"hue\": \"#00aaff\"\n },\n {\n \"saturation\": -100\n },\n {\n \"gamma\": 2.15\n },\n {\n \"lightness\": 12\n }\n ]\n },\n {\n \"featureType\": \"road\",\n \"elementType\": \"labels.text.fill\",\n \"stylers\": [\n {\n \"visibility\": \"on\"\n },\n {\n \"lightness\": 24\n }\n ]\n },\n {\n \"featureType\": \"road\",\n \"elementType\": \"geometry\",\n \"stylers\": [\n {\n \"lightness\": 57\n }\n ]\n }\n]\n", "import styles from \"./styles.json\";\n\nconst GOOGLE_MAPS_API_KEY = \"AIzaSyCu0RFsEPzifkgirE_Ge5aoRr2tfQHknY0\";\n\nclass ClusterMap {\n static init(maps = document.querySelectorAll(\"gmp-map\")) {\n maps.forEach((mapElement) => new ClusterMap(mapElement));\n }\n\n constructor(mapElement) {\n this.element = mapElement;\n const { innerMap: map } = mapElement;\n const styledMapType = new google.maps.StyledMapType(styles);\n map.mapTypes.set(\"styled_map\", styledMapType);\n map.setMapTypeId(\"styled_map\");\n\n const markers = mapElement.querySelectorAll(\"gmp-advanced-marker\");\n\n markers.forEach((marker) => {\n const dialog = marker.querySelector(\"dialog\");\n const close = dialog.querySelector(\"button\");\n\n marker.addEventListener(\"click\", (domEvent) => {\n this.select(marker);\n map.panTo(marker.position);\n\n //marker.classList.remove(\"hidden\");\n const { target } = domEvent;\n markers.forEach((m) => {\n const otherDialog = m.querySelector(\"dialog\");\n if (otherDialog !== target) {\n otherDialog.close();\n }\n });\n\n if (target === close) {\n if (dialog.open) {\n dialog.close();\n }\n return;\n }\n dialog.show();\n });\n });\n }\n\n /**\n * Adds selected markers\n */\n select(...markers) {\n const event = new CustomEvent(\"gmp-markerschange\", {\n detail: markers,\n });\n this.element.dispatchEvent(event);\n }\n\n /**\n * Renders a cluster as a single marker.\n *\n * Here we clone the first marker in the cluster, assuming that it\n * is an icon, and replace the text content with the count of markers\n * and remove \"icon\" class if any.\n */\n render({ count, position, markers }, stats, map) {\n // Clones the first marker in the cluster.\n const marker = markers[0].cloneNode(true);\n marker.position = position;\n marker.title = `Cluster of ${count} markers`;\n\n const content = marker.querySelector(\"button\");\n content.textContent = count;\n content.classList.remove(\"icon\");\n\n marker.content = content;\n\n marker.addEventListener(\"gmp-click\", () => {\n this.select(...markers);\n });\n\n return marker;\n }\n}\n\nconst maps = document.querySelectorAll(\"gmp-map\");\n\nif (maps.length) {\n (g=>{var h,a,k,p=\"The Google Maps JavaScript API\",c=\"google\",l=\"importLibrary\",q=\"__ib__\",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement(\"script\"));e.set(\"libraries\",[...r]+\"\");for(k in g)e.set(k.replace(/[A-Z]/g,t=>\"_\"+t[0].toLowerCase()),g[k]);e.set(\"callback\",c+\".maps.\"+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+\" could not load.\"));a.nonce=m.querySelector(\"script[nonce]\")?.nonce||\"\";m.head.append(a)}));d[l]?console.warn(p+\" only loads once. Ignoring:\",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({\n key: GOOGLE_MAPS_API_KEY,\n v: \"beta\",\n // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).\n // Add other bootstrap parameters as needed, using camel case.\n });\n\n Promise.all([\n google.maps.importLibrary(\"maps\"),\n google.maps.importLibrary(\"marker\"),\n ]).then(() => {\n maps.forEach((mapElement) => {\n const map = new ClusterMap(mapElement);\n });\n });\n}\n\nconst regionSelector = document.querySelector(\".region-selector\");\nconst mediaQuery = window.matchMedia(\"(max-width: 768px)\");\n\nfunction adjustRegionSelector(){\n if (mediaQuery.matches) {\n regionSelector.removeAttribute(\"open\");\n } else {\n regionSelector.setAttribute(\"open\", \"\");\n }\n}\n\nif (regionSelector) {\n var callResize;\n window.onresize = function(){\n clearTimeout(callResize);\n callResize = setTimeout(adjustRegionSelector, 100);\n };\n adjustRegionSelector();\n}\n", "import {\n cellDataType,\n cellType,\n columnSettingsType,\n inputCellType,\n nodeType,\n textNodeType\n} from \"./types\"\n\n/**\n * Check is item is object\n */\nexport const isObject = (val: (string | number | boolean | object | null | undefined )) => Object.prototype.toString.call(val) === \"[object Object]\"\n\n/**\n * Check for valid JSON string\n */\nexport const isJson = (str: string) => {\n let t = !1\n try {\n t = JSON.parse(str)\n } catch (e) {\n return !1\n }\n return !(null === t || (!Array.isArray(t) && !isObject(t))) && t\n}\n\n/**\n * Create DOM element node\n */\nexport const createElement = (nodeName: string, attrs?: { [key: string]: string}) => {\n const dom = document.createElement(nodeName)\n if (attrs && \"object\" == typeof attrs) {\n for (const attr in attrs) {\n if (\"html\" === attr) {\n dom.innerHTML = attrs[attr]\n } else {\n dom.setAttribute(attr, attrs[attr])\n }\n }\n }\n return dom\n}\n\nexport const objToText = (obj: nodeType) => {\n if ([\"#text\", \"#comment\"].includes(obj.nodeName)) {\n return (obj as textNodeType).data\n }\n if (obj.childNodes) {\n return obj.childNodes.map((childNode: nodeType) => objToText(childNode)).join(\"\")\n }\n return \"\"\n}\n\nexport const cellToText = (obj: inputCellType | cellDataType | null | undefined): string => {\n if (obj === null || obj === undefined) {\n return \"\"\n } else if (obj.hasOwnProperty(\"text\") || obj.hasOwnProperty(\"data\")) {\n const cell = obj as cellType\n return cell.text ?? cellToText(cell.data)\n } else if (obj.hasOwnProperty(\"nodeName\")) {\n return objToText(obj as nodeType)\n }\n return String(obj)\n}\n\n\nexport const escapeText = function(text: string) {\n return text\n .replace(/&/g, \"&\")\n .replace(//g, \">\")\n .replace(/\"/g, \""\")\n}\n\n\nexport const visibleToColumnIndex = function(visibleIndex: number, columns: columnSettingsType[]) {\n let counter = 0\n let columnIndex = 0\n while (counter < (visibleIndex+1)) {\n const columnSettings = columns[columnIndex]\n if (!columnSettings.hidden) {\n counter += 1\n }\n columnIndex += 1\n }\n return columnIndex-1\n}\n\nexport const columnToVisibleIndex = function(columnIndex: number, columns: columnSettingsType[]) {\n let visibleIndex = columnIndex\n let counter = 0\n while (counter < columnIndex) {\n const columnSettings = columns[counter]\n if (columnSettings.hidden) {\n visibleIndex -= 1\n }\n counter++\n }\n return visibleIndex\n}\n\n/**\n * Converts a [NamedNodeMap](https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap) into a normal object.\n *\n * @param map The `NamedNodeMap` to convert\n */\nexport const namedNodeMapToObject = function(map: NamedNodeMap) {\n const obj = {}\n if (map) {\n for (const attr of map) {\n obj[attr.name] = attr.value\n }\n }\n return obj\n}\n\n/**\n * Convert class names to a CSS selector. Multiple classes should be separated by spaces.\n * Examples:\n * - \"my-class\" -> \".my-class\"\n * - \"my-class second-class\" -> \".my-class.second-class\"\n *\n * @param classNames The class names to convert. Can contain multiple classes separated by spaces.\n */\nexport const classNamesToSelector = (classNames: string) => {\n if (!classNames) {\n return null\n }\n return classNames.trim().split(\" \").map(className => `.${className}`).join(\"\")\n}\n\n/**\n * Check if the element contains all the classes. Multiple classes should be separated by spaces.\n *\n * @param element The element that will be checked\n * @param classes The classes that must be present in the element. Can contain multiple classes separated by spaces.\n */\nexport const containsClass = (element: Element, classes: string) => {\n const hasMissingClass = classes?.split(\" \").some(className => !element.classList.contains(className))\n return !hasMissingClass\n}\n\n/**\n * Join two strings with spaces. Null values are ignored.\n * Examples:\n * - joinWithSpaces(\"a\", \"b\") -> \"a b\"\n * - joinWithSpaces(\"a\", null) -> \"a\"\n * - joinWithSpaces(null, \"b\") -> \"b\"\n * - joinWithSpaces(\"a\", \"b c\") -> \"a b c\"\n *\n * @param first The first string to join\n * @param second The second string to join\n */\nexport const joinWithSpaces = (first: string | null | undefined, second: string | null | undefined) => {\n if (first) {\n if (second) {\n return `${first} ${second}`\n }\n return first\n } else if (second) {\n return second\n }\n return \"\"\n}\n\n// Source: https://www.freecodecamp.org/news/javascript-debounce-example/\n\nexport const debounce = function(func: () => void, timeout = 300) {\n let timer: number\n return (..._args: any[]) => {\n clearTimeout(timer)\n timer = window.setTimeout(() => func(), timeout)\n }\n}\n", "/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol */\r\n\r\n\r\nvar __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\n var arguments$1 = arguments;\n\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments$1[i];\r\n for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p)) { t[p] = s[p]; } }\r\n }\r\n return t;\r\n };\r\n return __assign.apply(this, arguments);\r\n};\r\n\r\nfunction __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) { for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) { ar = Array.prototype.slice.call(from, 0, i); }\r\n ar[i] = from[i];\r\n }\r\n } }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\ntypeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\n\nvar Diff = /** @class */ (function () {\n function Diff(options) {\n if (options === void 0) { options = {}; }\n var _this = this;\n Object.entries(options).forEach(function (_a) {\n var key = _a[0], value = _a[1];\n return (_this[key] = value);\n });\n }\n Diff.prototype.toString = function () {\n return JSON.stringify(this);\n };\n Diff.prototype.setValue = function (aKey, aValue) {\n this[aKey] = aValue;\n return this;\n };\n return Diff;\n}());\nfunction checkElementType(element) {\n var arguments$1 = arguments;\n\n var elementTypeNames = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n elementTypeNames[_i - 1] = arguments$1[_i];\n }\n if (typeof element === \"undefined\" || element === null) {\n return false;\n }\n return elementTypeNames.some(function (elementTypeName) {\n var _a, _b;\n // We need to check if the specified type is defined\n // because otherwise instanceof throws an exception.\n return typeof ((_b = (_a = element === null || element === void 0 ? void 0 : element.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) === null || _b === void 0 ? void 0 : _b[elementTypeName]) ===\n \"function\" &&\n element instanceof\n element.ownerDocument.defaultView[elementTypeName];\n });\n}\n\nfunction objToNode(objNode, insideSvg, options) {\n var node;\n if (objNode.nodeName === \"#text\") {\n node = options.document.createTextNode(objNode.data);\n }\n else if (objNode.nodeName === \"#comment\") {\n node = options.document.createComment(objNode.data);\n }\n else {\n if (insideSvg) {\n node = options.document.createElementNS(\"http://www.w3.org/2000/svg\", objNode.nodeName);\n if (objNode.nodeName === \"foreignObject\") {\n insideSvg = false;\n }\n }\n else if (objNode.nodeName.toLowerCase() === \"svg\") {\n node = options.document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n insideSvg = true;\n }\n else {\n node = options.document.createElement(objNode.nodeName);\n }\n if (objNode.attributes) {\n Object.entries(objNode.attributes).forEach(function (_a) {\n var key = _a[0], value = _a[1];\n return node.setAttribute(key, value);\n });\n }\n if (objNode.childNodes) {\n node = node;\n objNode.childNodes.forEach(function (childNode) {\n return node.appendChild(objToNode(childNode, insideSvg, options));\n });\n }\n if (options.valueDiffing) {\n if (objNode.value &&\n checkElementType(node, \"HTMLButtonElement\", \"HTMLDataElement\", \"HTMLInputElement\", \"HTMLLIElement\", \"HTMLMeterElement\", \"HTMLOptionElement\", \"HTMLProgressElement\", \"HTMLParamElement\")) {\n node.value = objNode.value;\n }\n if (objNode.checked && checkElementType(node, \"HTMLInputElement\")) {\n node.checked = objNode.checked;\n }\n if (objNode.selected &&\n checkElementType(node, \"HTMLOptionElement\")) {\n node.selected = objNode.selected;\n }\n }\n }\n return node;\n}\n\n// ===== Apply a diff =====\nvar getFromRoute = function (node, route) {\n route = route.slice();\n while (route.length > 0) {\n var c = route.splice(0, 1)[0];\n node = node.childNodes[c];\n }\n return node;\n};\nfunction applyDiff(tree, diff, options) {\n var action = diff[options._const.action];\n var route = diff[options._const.route];\n var node;\n if (![options._const.addElement, options._const.addTextElement].includes(action)) {\n // For adding nodes, we calculate the route later on. It's different because it includes the position of the newly added item.\n node = getFromRoute(tree, route);\n }\n var newNode;\n var reference;\n var nodeArray;\n // pre-diff hook\n var info = {\n diff: diff,\n node: node\n };\n if (options.preDiffApply(info)) {\n return true;\n }\n switch (action) {\n case options._const.addAttribute:\n if (!node || !checkElementType(node, \"Element\")) {\n return false;\n }\n node.setAttribute(diff[options._const.name], diff[options._const.value]);\n break;\n case options._const.modifyAttribute:\n if (!node || !checkElementType(node, \"Element\")) {\n return false;\n }\n node.setAttribute(diff[options._const.name], diff[options._const.newValue]);\n if (checkElementType(node, \"HTMLInputElement\") &&\n diff[options._const.name] === \"value\") {\n node.value = diff[options._const.newValue];\n }\n break;\n case options._const.removeAttribute:\n if (!node || !checkElementType(node, \"Element\")) {\n return false;\n }\n node.removeAttribute(diff[options._const.name]);\n break;\n case options._const.modifyTextElement:\n if (!node || !checkElementType(node, \"Text\")) {\n return false;\n }\n options.textDiff(node, node.data, diff[options._const.oldValue], diff[options._const.newValue]);\n if (checkElementType(node.parentNode, \"HTMLTextAreaElement\")) {\n node.parentNode.value = diff[options._const.newValue];\n }\n break;\n case options._const.modifyValue:\n if (!node || typeof node.value === \"undefined\") {\n return false;\n }\n node.value = diff[options._const.newValue];\n break;\n case options._const.modifyComment:\n if (!node || !checkElementType(node, \"Comment\")) {\n return false;\n }\n options.textDiff(node, node.data, diff[options._const.oldValue], diff[options._const.newValue]);\n break;\n case options._const.modifyChecked:\n if (!node || typeof node.checked === \"undefined\") {\n return false;\n }\n node.checked = diff[options._const.newValue];\n break;\n case options._const.modifySelected:\n if (!node || typeof node.selected === \"undefined\") {\n return false;\n }\n node.selected = diff[options._const.newValue];\n break;\n case options._const.replaceElement: {\n var insideSvg = diff[options._const.newValue].nodeName.toLowerCase() === \"svg\" ||\n node.parentNode.namespaceURI === \"http://www.w3.org/2000/svg\";\n node.parentNode.replaceChild(objToNode(diff[options._const.newValue], insideSvg, options), node);\n break;\n }\n case options._const.relocateGroup:\n nodeArray = __spreadArray([], new Array(diff[options._const.groupLength]), true).map(function () {\n return node.removeChild(node.childNodes[diff[options._const.from]]);\n });\n nodeArray.forEach(function (childNode, index) {\n if (index === 0) {\n reference =\n node.childNodes[diff[options._const.to]];\n }\n node.insertBefore(childNode, reference || null);\n });\n break;\n case options._const.removeElement:\n node.parentNode.removeChild(node);\n break;\n case options._const.addElement: {\n var parentRoute = route.slice();\n var c = parentRoute.splice(parentRoute.length - 1, 1)[0];\n node = getFromRoute(tree, parentRoute);\n if (!checkElementType(node, \"Element\")) {\n return false;\n }\n node.insertBefore(objToNode(diff[options._const.element], node.namespaceURI === \"http://www.w3.org/2000/svg\", options), node.childNodes[c] || null);\n break;\n }\n case options._const.removeTextElement: {\n if (!node || node.nodeType !== 3) {\n return false;\n }\n var parentNode = node.parentNode;\n parentNode.removeChild(node);\n if (checkElementType(parentNode, \"HTMLTextAreaElement\")) {\n parentNode.value = \"\";\n }\n break;\n }\n case options._const.addTextElement: {\n var parentRoute = route.slice();\n var c = parentRoute.splice(parentRoute.length - 1, 1)[0];\n newNode = options.document.createTextNode(diff[options._const.value]);\n node = getFromRoute(tree, parentRoute);\n if (!node.childNodes) {\n return false;\n }\n node.insertBefore(newNode, node.childNodes[c] || null);\n if (checkElementType(node.parentNode, \"HTMLTextAreaElement\")) {\n node.parentNode.value = diff[options._const.value];\n }\n break;\n }\n default:\n console.log(\"unknown action\");\n }\n // if a new node was created, we might be interested in its\n // post diff hook\n options.postDiffApply({\n diff: info.diff,\n node: info.node,\n newNode: newNode\n });\n return true;\n}\nfunction applyDOM(tree, diffs, options) {\n return diffs.every(function (diff) {\n return applyDiff(tree, diff, options);\n });\n}\n\n// ===== Undo a diff =====\nfunction swap(obj, p1, p2) {\n var tmp = obj[p1];\n obj[p1] = obj[p2];\n obj[p2] = tmp;\n}\nfunction undoDiff(tree, diff, options) {\n switch (diff[options._const.action]) {\n case options._const.addAttribute:\n diff[options._const.action] = options._const.removeAttribute;\n applyDiff(tree, diff, options);\n break;\n case options._const.modifyAttribute:\n swap(diff, options._const.oldValue, options._const.newValue);\n applyDiff(tree, diff, options);\n break;\n case options._const.removeAttribute:\n diff[options._const.action] = options._const.addAttribute;\n applyDiff(tree, diff, options);\n break;\n case options._const.modifyTextElement:\n swap(diff, options._const.oldValue, options._const.newValue);\n applyDiff(tree, diff, options);\n break;\n case options._const.modifyValue:\n swap(diff, options._const.oldValue, options._const.newValue);\n applyDiff(tree, diff, options);\n break;\n case options._const.modifyComment:\n swap(diff, options._const.oldValue, options._const.newValue);\n applyDiff(tree, diff, options);\n break;\n case options._const.modifyChecked:\n swap(diff, options._const.oldValue, options._const.newValue);\n applyDiff(tree, diff, options);\n break;\n case options._const.modifySelected:\n swap(diff, options._const.oldValue, options._const.newValue);\n applyDiff(tree, diff, options);\n break;\n case options._const.replaceElement:\n swap(diff, options._const.oldValue, options._const.newValue);\n applyDiff(tree, diff, options);\n break;\n case options._const.relocateGroup:\n swap(diff, options._const.from, options._const.to);\n applyDiff(tree, diff, options);\n break;\n case options._const.removeElement:\n diff[options._const.action] = options._const.addElement;\n applyDiff(tree, diff, options);\n break;\n case options._const.addElement:\n diff[options._const.action] = options._const.removeElement;\n applyDiff(tree, diff, options);\n break;\n case options._const.removeTextElement:\n diff[options._const.action] = options._const.addTextElement;\n applyDiff(tree, diff, options);\n break;\n case options._const.addTextElement:\n diff[options._const.action] = options._const.removeTextElement;\n applyDiff(tree, diff, options);\n break;\n default:\n console.log(\"unknown action\");\n }\n}\nfunction undoDOM(tree, diffs, options) {\n diffs = diffs.slice();\n diffs.reverse();\n diffs.forEach(function (diff) {\n undoDiff(tree, diff, options);\n });\n}\n\nvar elementDescriptors = function (el) {\n var output = [];\n output.push(el.nodeName);\n if (el.nodeName !== \"#text\" && el.nodeName !== \"#comment\") {\n el = el;\n if (el.attributes) {\n if (el.attributes[\"class\"]) {\n output.push(\"\".concat(el.nodeName, \".\").concat(el.attributes[\"class\"].replace(/ /g, \".\")));\n }\n if (el.attributes.id) {\n output.push(\"\".concat(el.nodeName, \"#\").concat(el.attributes.id));\n }\n }\n }\n return output;\n};\nvar findUniqueDescriptors = function (li) {\n var uniqueDescriptors = {};\n var duplicateDescriptors = {};\n li.forEach(function (node) {\n elementDescriptors(node).forEach(function (descriptor) {\n var inUnique = descriptor in uniqueDescriptors;\n var inDupes = descriptor in duplicateDescriptors;\n if (!inUnique && !inDupes) {\n uniqueDescriptors[descriptor] = true;\n }\n else if (inUnique) {\n delete uniqueDescriptors[descriptor];\n duplicateDescriptors[descriptor] = true;\n }\n });\n });\n return uniqueDescriptors;\n};\nvar uniqueInBoth = function (l1, l2) {\n var l1Unique = findUniqueDescriptors(l1);\n var l2Unique = findUniqueDescriptors(l2);\n var inBoth = {};\n Object.keys(l1Unique).forEach(function (key) {\n if (l2Unique[key]) {\n inBoth[key] = true;\n }\n });\n return inBoth;\n};\nvar removeDone = function (tree) {\n delete tree.outerDone;\n delete tree.innerDone;\n delete tree.valueDone;\n if (tree.childNodes) {\n return tree.childNodes.every(removeDone);\n }\n else {\n return true;\n }\n};\nvar cleanNode = function (diffNode) {\n if (Object.prototype.hasOwnProperty.call(diffNode, \"data\")) {\n var textNode = {\n nodeName: diffNode.nodeName === \"#text\" ? \"#text\" : \"#comment\",\n data: diffNode.data\n };\n return textNode;\n }\n else {\n var elementNode = {\n nodeName: diffNode.nodeName\n };\n diffNode = diffNode;\n if (Object.prototype.hasOwnProperty.call(diffNode, \"attributes\")) {\n elementNode.attributes = __assign({}, diffNode.attributes);\n }\n if (Object.prototype.hasOwnProperty.call(diffNode, \"checked\")) {\n elementNode.checked = diffNode.checked;\n }\n if (Object.prototype.hasOwnProperty.call(diffNode, \"value\")) {\n elementNode.value = diffNode.value;\n }\n if (Object.prototype.hasOwnProperty.call(diffNode, \"selected\")) {\n elementNode.selected = diffNode.selected;\n }\n if (Object.prototype.hasOwnProperty.call(diffNode, \"childNodes\")) {\n elementNode.childNodes = diffNode.childNodes.map(function (diffChildNode) {\n return cleanNode(diffChildNode);\n });\n }\n return elementNode;\n }\n};\nvar isEqual = function (e1, e2) {\n if (![\"nodeName\", \"value\", \"checked\", \"selected\", \"data\"].every(function (element) {\n if (e1[element] !== e2[element]) {\n return false;\n }\n return true;\n })) {\n return false;\n }\n if (Object.prototype.hasOwnProperty.call(e1, \"data\")) {\n // Comment or Text\n return true;\n }\n e1 = e1;\n e2 = e2;\n if (Boolean(e1.attributes) !== Boolean(e2.attributes)) {\n return false;\n }\n if (Boolean(e1.childNodes) !== Boolean(e2.childNodes)) {\n return false;\n }\n if (e1.attributes) {\n var e1Attributes = Object.keys(e1.attributes);\n var e2Attributes = Object.keys(e2.attributes);\n if (e1Attributes.length !== e2Attributes.length) {\n return false;\n }\n if (!e1Attributes.every(function (attribute) {\n if (e1.attributes[attribute] !==\n e2.attributes[attribute]) {\n return false;\n }\n return true;\n })) {\n return false;\n }\n }\n if (e1.childNodes) {\n if (e1.childNodes.length !== e2.childNodes.length) {\n return false;\n }\n if (!e1.childNodes.every(function (childNode, index) {\n return isEqual(childNode, e2.childNodes[index]);\n })) {\n return false;\n }\n }\n return true;\n};\nvar roughlyEqual = function (e1, e2, uniqueDescriptors, sameSiblings, preventRecursion) {\n if (preventRecursion === void 0) { preventRecursion = false; }\n if (!e1 || !e2) {\n return false;\n }\n if (e1.nodeName !== e2.nodeName) {\n return false;\n }\n if ([\"#text\", \"#comment\"].includes(e1.nodeName)) {\n // Note that we initially don't care what the text content of a node is,\n // the mere fact that it's the same tag and \"has text\" means it's roughly\n // equal, and then we can find out the true text difference later.\n return preventRecursion\n ? true\n : e1.data === e2.data;\n }\n e1 = e1;\n e2 = e2;\n if (e1.nodeName in uniqueDescriptors) {\n return true;\n }\n if (e1.attributes && e2.attributes) {\n if (e1.attributes.id) {\n if (e1.attributes.id !== e2.attributes.id) {\n return false;\n }\n else {\n var idDescriptor = \"\".concat(e1.nodeName, \"#\").concat(e1.attributes.id);\n if (idDescriptor in uniqueDescriptors) {\n return true;\n }\n }\n }\n if (e1.attributes[\"class\"] &&\n e1.attributes[\"class\"] === e2.attributes[\"class\"]) {\n var classDescriptor = \"\".concat(e1.nodeName, \".\").concat(e1.attributes[\"class\"].replace(/ /g, \".\"));\n if (classDescriptor in uniqueDescriptors) {\n return true;\n }\n }\n }\n if (sameSiblings) {\n return true;\n }\n var nodeList1 = e1.childNodes ? e1.childNodes.slice().reverse() : [];\n var nodeList2 = e2.childNodes ? e2.childNodes.slice().reverse() : [];\n if (nodeList1.length !== nodeList2.length) {\n return false;\n }\n if (preventRecursion) {\n return nodeList1.every(function (element, index) {\n return element.nodeName === nodeList2[index].nodeName;\n });\n }\n else {\n // note: we only allow one level of recursion at any depth. If 'preventRecursion'\n // was not set, we must explicitly force it to true for child iterations.\n var childUniqueDescriptors_1 = uniqueInBoth(nodeList1, nodeList2);\n return nodeList1.every(function (element, index) {\n return roughlyEqual(element, nodeList2[index], childUniqueDescriptors_1, true, true);\n });\n }\n};\n/**\n * based on https://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Longest_common_substring#JavaScript\n */\nvar findCommonSubsets = function (c1, c2, marked1, marked2) {\n var lcsSize = 0;\n var index = [];\n var c1Length = c1.length;\n var c2Length = c2.length;\n var // set up the matching table\n matches = __spreadArray([], new Array(c1Length + 1), true).map(function () { return []; });\n var uniqueDescriptors = uniqueInBoth(c1, c2);\n var // If all of the elements are the same tag, id and class, then we can\n // consider them roughly the same even if they have a different number of\n // children. This will reduce removing and re-adding similar elements.\n subsetsSame = c1Length === c2Length;\n if (subsetsSame) {\n c1.some(function (element, i) {\n var c1Desc = elementDescriptors(element);\n var c2Desc = elementDescriptors(c2[i]);\n if (c1Desc.length !== c2Desc.length) {\n subsetsSame = false;\n return true;\n }\n c1Desc.some(function (description, i) {\n if (description !== c2Desc[i]) {\n subsetsSame = false;\n return true;\n }\n });\n if (!subsetsSame) {\n return true;\n }\n });\n }\n // fill the matches with distance values\n for (var c1Index = 0; c1Index < c1Length; c1Index++) {\n var c1Element = c1[c1Index];\n for (var c2Index = 0; c2Index < c2Length; c2Index++) {\n var c2Element = c2[c2Index];\n if (!marked1[c1Index] &&\n !marked2[c2Index] &&\n roughlyEqual(c1Element, c2Element, uniqueDescriptors, subsetsSame)) {\n matches[c1Index + 1][c2Index + 1] = matches[c1Index][c2Index]\n ? matches[c1Index][c2Index] + 1\n : 1;\n if (matches[c1Index + 1][c2Index + 1] >= lcsSize) {\n lcsSize = matches[c1Index + 1][c2Index + 1];\n index = [c1Index + 1, c2Index + 1];\n }\n }\n else {\n matches[c1Index + 1][c2Index + 1] = 0;\n }\n }\n }\n if (lcsSize === 0) {\n return false;\n }\n return {\n oldValue: index[0] - lcsSize,\n newValue: index[1] - lcsSize,\n length: lcsSize\n };\n};\nvar makeBooleanArray = function (n, v) {\n return __spreadArray([], new Array(n), true).map(function () { return v; });\n};\n/**\n * Generate arrays that indicate which node belongs to which subset,\n * or whether it's actually an orphan node, existing in only one\n * of the two trees, rather than somewhere in both.\n *\n * So if t1 =
, t2 =
.\n * The longest subset is \"
\" (length 2), so it will group 0.\n * The second longest is \"\" (length 1), so it will be group 1.\n * gaps1 will therefore be [1,0,0] and gaps2 [0,0,1].\n *\n * If an element is not part of any group, it will stay being 'true', which\n * is the initial value. For example:\n * t1 =


, t2 =
\n *\n * The \"

\" and \"\" do only show up in one of the two and will\n * therefore be marked by \"true\". The remaining parts are parts of the\n * groups 0 and 1:\n * gaps1 = [1, true, 0, 0], gaps2 = [true, 0, 0, 1]\n *\n */\nvar getGapInformation = function (t1, t2, stable) {\n var gaps1 = t1.childNodes\n ? makeBooleanArray(t1.childNodes.length, true)\n : [];\n var gaps2 = t2.childNodes\n ? makeBooleanArray(t2.childNodes.length, true)\n : [];\n var group = 0;\n // give elements from the same subset the same group number\n stable.forEach(function (subset) {\n var endOld = subset.oldValue + subset.length;\n var endNew = subset.newValue + subset.length;\n for (var j = subset.oldValue; j < endOld; j += 1) {\n gaps1[j] = group;\n }\n for (var j = subset.newValue; j < endNew; j += 1) {\n gaps2[j] = group;\n }\n group += 1;\n });\n return {\n gaps1: gaps1,\n gaps2: gaps2\n };\n};\n/**\n * Find all matching subsets, based on immediate child differences only.\n */\nvar markBoth = function (marked1, marked2, subset, i) {\n marked1[subset.oldValue + i] = true;\n marked2[subset.newValue + i] = true;\n};\nvar markSubTrees = function (oldTree, newTree) {\n // note: the child lists are views, and so update as we update old/newTree\n var oldChildren = oldTree.childNodes ? oldTree.childNodes : [];\n var newChildren = newTree.childNodes ? newTree.childNodes : [];\n var marked1 = makeBooleanArray(oldChildren.length, false);\n var marked2 = makeBooleanArray(newChildren.length, false);\n var subsets = [];\n var returnIndex = function () {\n return arguments[1];\n };\n var foundAllSubsets = false;\n var _loop_1 = function () {\n var subset = findCommonSubsets(oldChildren, newChildren, marked1, marked2);\n if (subset) {\n subsets.push(subset);\n var subsetArray = __spreadArray([], new Array(subset.length), true).map(returnIndex);\n subsetArray.forEach(function (item) {\n return markBoth(marked1, marked2, subset, item);\n });\n }\n else {\n foundAllSubsets = true;\n }\n };\n while (!foundAllSubsets) {\n _loop_1();\n }\n oldTree.subsets = subsets;\n oldTree.subsetsAge = 100;\n return subsets;\n};\nvar DiffTracker = /** @class */ (function () {\n function DiffTracker() {\n this.list = [];\n }\n DiffTracker.prototype.add = function (diffs) {\n var _a;\n (_a = this.list).push.apply(_a, diffs);\n };\n DiffTracker.prototype.forEach = function (fn) {\n this.list.forEach(function (li) { return fn(li); });\n };\n return DiffTracker;\n}());\n\n// ===== Apply a virtual diff =====\nfunction getFromVirtualRoute(tree, route) {\n var node = tree;\n var parentNode;\n var nodeIndex;\n route = route.slice();\n while (route.length > 0) {\n nodeIndex = route.splice(0, 1)[0];\n parentNode = node;\n node = node.childNodes ? node.childNodes[nodeIndex] : undefined;\n }\n return {\n node: node,\n parentNode: parentNode,\n nodeIndex: nodeIndex\n };\n}\nfunction applyVirtualDiff(tree, diff, options) {\n var _a;\n var node, parentNode, nodeIndex;\n if (![options._const.addElement, options._const.addTextElement].includes(diff[options._const.action])) {\n // For adding nodes, we calculate the route later on. It's different because it includes the position of the newly added item.\n var routeInfo = getFromVirtualRoute(tree, diff[options._const.route]);\n node = routeInfo.node;\n parentNode = routeInfo.parentNode;\n nodeIndex = routeInfo.nodeIndex;\n }\n var newSubsets = [];\n // pre-diff hook\n var info = {\n diff: diff,\n node: node\n };\n if (options.preVirtualDiffApply(info)) {\n return true;\n }\n var newNode;\n var nodeArray;\n var route;\n switch (diff[options._const.action]) {\n case options._const.addAttribute:\n if (!node.attributes) {\n node.attributes = {};\n }\n node.attributes[diff[options._const.name]] =\n diff[options._const.value];\n if (diff[options._const.name] === \"checked\") {\n node.checked = true;\n }\n else if (diff[options._const.name] === \"selected\") {\n node.selected = true;\n }\n else if (node.nodeName === \"INPUT\" &&\n diff[options._const.name] === \"value\") {\n node.value = diff[options._const.value];\n }\n break;\n case options._const.modifyAttribute:\n node.attributes[diff[options._const.name]] =\n diff[options._const.newValue];\n break;\n case options._const.removeAttribute:\n delete node.attributes[diff[options._const.name]];\n if (Object.keys(node.attributes).length === 0) {\n delete node.attributes;\n }\n if (diff[options._const.name] === \"checked\") {\n node.checked = false;\n }\n else if (diff[options._const.name] === \"selected\") {\n delete node.selected;\n }\n else if (node.nodeName === \"INPUT\" &&\n diff[options._const.name] === \"value\") {\n delete node.value;\n }\n break;\n case options._const.modifyTextElement:\n node.data = diff[options._const.newValue];\n if (parentNode.nodeName === \"TEXTAREA\") {\n parentNode.value = diff[options._const.newValue];\n }\n break;\n case options._const.modifyValue:\n node.value = diff[options._const.newValue];\n break;\n case options._const.modifyComment:\n node.data = diff[options._const.newValue];\n break;\n case options._const.modifyChecked:\n node.checked = diff[options._const.newValue];\n break;\n case options._const.modifySelected:\n node.selected = diff[options._const.newValue];\n break;\n case options._const.replaceElement:\n newNode = cleanNode(diff[options._const.newValue]);\n parentNode.childNodes[nodeIndex] = newNode;\n break;\n case options._const.relocateGroup:\n nodeArray = node.childNodes\n .splice(diff[options._const.from], diff[options._const.groupLength])\n .reverse();\n nodeArray.forEach(function (movedNode) {\n return node.childNodes.splice(diff[options._const.to], 0, movedNode);\n });\n if (node.subsets) {\n node.subsets.forEach(function (map) {\n if (diff[options._const.from] < diff[options._const.to] &&\n map.oldValue <= diff[options._const.to] &&\n map.oldValue > diff[options._const.from]) {\n map.oldValue -= diff[options._const.groupLength];\n var splitLength = map.oldValue + map.length - diff[options._const.to];\n if (splitLength > 0) {\n // new insertion splits map.\n newSubsets.push({\n oldValue: diff[options._const.to] +\n diff[options._const.groupLength],\n newValue: map.newValue + map.length - splitLength,\n length: splitLength\n });\n map.length -= splitLength;\n }\n }\n else if (diff[options._const.from] > diff[options._const.to] &&\n map.oldValue > diff[options._const.to] &&\n map.oldValue < diff[options._const.from]) {\n map.oldValue += diff[options._const.groupLength];\n var splitLength = map.oldValue + map.length - diff[options._const.to];\n if (splitLength > 0) {\n // new insertion splits map.\n newSubsets.push({\n oldValue: diff[options._const.to] +\n diff[options._const.groupLength],\n newValue: map.newValue + map.length - splitLength,\n length: splitLength\n });\n map.length -= splitLength;\n }\n }\n else if (map.oldValue === diff[options._const.from]) {\n map.oldValue = diff[options._const.to];\n }\n });\n }\n break;\n case options._const.removeElement:\n parentNode.childNodes.splice(nodeIndex, 1);\n if (parentNode.subsets) {\n parentNode.subsets.forEach(function (map) {\n if (map.oldValue > nodeIndex) {\n map.oldValue -= 1;\n }\n else if (map.oldValue === nodeIndex) {\n map[\"delete\"] = true;\n }\n else if (map.oldValue < nodeIndex &&\n map.oldValue + map.length > nodeIndex) {\n if (map.oldValue + map.length - 1 === nodeIndex) {\n map.length--;\n }\n else {\n newSubsets.push({\n newValue: map.newValue + nodeIndex - map.oldValue,\n oldValue: nodeIndex,\n length: map.length - nodeIndex + map.oldValue - 1\n });\n map.length = nodeIndex - map.oldValue;\n }\n }\n });\n }\n node = parentNode;\n break;\n case options._const.addElement: {\n route = diff[options._const.route].slice();\n var c_1 = route.splice(route.length - 1, 1)[0];\n node = (_a = getFromVirtualRoute(tree, route)) === null || _a === void 0 ? void 0 : _a.node;\n newNode = cleanNode(diff[options._const.element]);\n if (!node.childNodes) {\n node.childNodes = [];\n }\n if (c_1 >= node.childNodes.length) {\n node.childNodes.push(newNode);\n }\n else {\n node.childNodes.splice(c_1, 0, newNode);\n }\n if (node.subsets) {\n node.subsets.forEach(function (map) {\n if (map.oldValue >= c_1) {\n map.oldValue += 1;\n }\n else if (map.oldValue < c_1 &&\n map.oldValue + map.length > c_1) {\n var splitLength = map.oldValue + map.length - c_1;\n newSubsets.push({\n newValue: map.newValue + map.length - splitLength,\n oldValue: c_1 + 1,\n length: splitLength\n });\n map.length -= splitLength;\n }\n });\n }\n break;\n }\n case options._const.removeTextElement:\n parentNode.childNodes.splice(nodeIndex, 1);\n if (parentNode.nodeName === \"TEXTAREA\") {\n delete parentNode.value;\n }\n if (parentNode.subsets) {\n parentNode.subsets.forEach(function (map) {\n if (map.oldValue > nodeIndex) {\n map.oldValue -= 1;\n }\n else if (map.oldValue === nodeIndex) {\n map[\"delete\"] = true;\n }\n else if (map.oldValue < nodeIndex &&\n map.oldValue + map.length > nodeIndex) {\n if (map.oldValue + map.length - 1 === nodeIndex) {\n map.length--;\n }\n else {\n newSubsets.push({\n newValue: map.newValue + nodeIndex - map.oldValue,\n oldValue: nodeIndex,\n length: map.length - nodeIndex + map.oldValue - 1\n });\n map.length = nodeIndex - map.oldValue;\n }\n }\n });\n }\n node = parentNode;\n break;\n case options._const.addTextElement: {\n route = diff[options._const.route].slice();\n var c_2 = route.splice(route.length - 1, 1)[0];\n newNode = {\n nodeName: \"#text\",\n data: diff[options._const.value]\n };\n node = getFromVirtualRoute(tree, route).node;\n if (!node.childNodes) {\n node.childNodes = [];\n }\n if (c_2 >= node.childNodes.length) {\n node.childNodes.push(newNode);\n }\n else {\n node.childNodes.splice(c_2, 0, newNode);\n }\n if (node.nodeName === \"TEXTAREA\") {\n node.value = diff[options._const.newValue];\n }\n if (node.subsets) {\n node.subsets.forEach(function (map) {\n if (map.oldValue >= c_2) {\n map.oldValue += 1;\n }\n if (map.oldValue < c_2 && map.oldValue + map.length > c_2) {\n var splitLength = map.oldValue + map.length - c_2;\n newSubsets.push({\n newValue: map.newValue + map.length - splitLength,\n oldValue: c_2 + 1,\n length: splitLength\n });\n map.length -= splitLength;\n }\n });\n }\n break;\n }\n default:\n console.log(\"unknown action\");\n }\n if (node.subsets) {\n node.subsets = node.subsets.filter(function (map) { return !map[\"delete\"] && map.oldValue !== map.newValue; });\n if (newSubsets.length) {\n node.subsets = node.subsets.concat(newSubsets);\n }\n }\n options.postVirtualDiffApply({\n node: info.node,\n diff: info.diff,\n newNode: newNode\n });\n return;\n}\nfunction applyVirtual(tree, diffs, options) {\n diffs.forEach(function (diff) {\n applyVirtualDiff(tree, diff, options);\n });\n return true;\n}\n\nfunction nodeToObj(aNode, options) {\n if (options === void 0) { options = { valueDiffing: true }; }\n var objNode = {\n nodeName: aNode.nodeName\n };\n if (checkElementType(aNode, \"Text\", \"Comment\")) {\n objNode.data = aNode.data;\n }\n else {\n if (aNode.attributes && aNode.attributes.length > 0) {\n objNode.attributes = {};\n var nodeArray = Array.prototype.slice.call(aNode.attributes);\n nodeArray.forEach(function (attribute) {\n return (objNode.attributes[attribute.name] = attribute.value);\n });\n }\n if (aNode.childNodes && aNode.childNodes.length > 0) {\n objNode.childNodes = [];\n var nodeArray = Array.prototype.slice.call(aNode.childNodes);\n nodeArray.forEach(function (childNode) {\n return objNode.childNodes.push(nodeToObj(childNode, options));\n });\n }\n if (options.valueDiffing) {\n if (checkElementType(aNode, \"HTMLTextAreaElement\")) {\n objNode.value = aNode.value;\n }\n if (checkElementType(aNode, \"HTMLInputElement\") &&\n [\"radio\", \"checkbox\"].includes(aNode.type.toLowerCase()) &&\n aNode.checked !== undefined) {\n objNode.checked = aNode.checked;\n }\n else if (checkElementType(aNode, \"HTMLButtonElement\", \"HTMLDataElement\", \"HTMLInputElement\", \"HTMLLIElement\", \"HTMLMeterElement\", \"HTMLOptionElement\", \"HTMLProgressElement\", \"HTMLParamElement\")) {\n objNode.value = aNode.value;\n }\n if (checkElementType(aNode, \"HTMLOptionElement\")) {\n objNode.selected = aNode.selected;\n }\n }\n }\n return objNode;\n}\n\n// from html-parse-stringify (MIT)\nvar tagRE = /<\\s*\\/*[a-zA-Z:_][a-zA-Z0-9:_\\-.]*\\s*(?:\"[^\"]*\"['\"]*|'[^']*'['\"]*|[^'\"/>])*\\/*\\s*>|/g;\nvar attrRE = /\\s([^'\"/\\s><]+?)[\\s/>]|([^\\s=]+)=\\s?(\".*?\"|'.*?')/g;\nfunction unescape(string) {\n return string\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/&/g, \"&\");\n}\n// create optimized lookup object for\n// void elements as listed here:\n// https://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements\nvar lookup = {\n area: true,\n base: true,\n br: true,\n col: true,\n embed: true,\n hr: true,\n img: true,\n input: true,\n keygen: true,\n link: true,\n menuItem: true,\n meta: true,\n param: true,\n source: true,\n track: true,\n wbr: true\n};\nvar parseTag = function (tag, caseSensitive) {\n var res = {\n nodeName: \"\",\n attributes: {}\n };\n var voidElement = false;\n var type = \"tag\";\n var tagMatch = tag.match(/<\\/?([^\\s]+?)[/\\s>]/);\n if (tagMatch) {\n res.nodeName =\n caseSensitive || tagMatch[1] === \"svg\"\n ? tagMatch[1]\n : tagMatch[1].toUpperCase();\n if (lookup[tagMatch[1]] || tag.charAt(tag.length - 2) === \"/\") {\n voidElement = true;\n }\n // handle comment tag\n if (res.nodeName.startsWith(\"!--\")) {\n var endIndex = tag.indexOf(\"-->\");\n return {\n type: \"comment\",\n node: {\n nodeName: \"#comment\",\n data: endIndex !== -1 ? tag.slice(4, endIndex) : \"\"\n },\n voidElement: voidElement\n };\n }\n }\n var reg = new RegExp(attrRE);\n var result = null;\n var done = false;\n while (!done) {\n result = reg.exec(tag);\n if (result === null) {\n done = true;\n }\n else if (result[0].trim()) {\n if (result[1]) {\n var attr = result[1].trim();\n var arr = [attr, \"\"];\n if (attr.indexOf(\"=\") > -1)\n { arr = attr.split(\"=\"); }\n res.attributes[arr[0]] = arr[1];\n reg.lastIndex--;\n }\n else if (result[2])\n { res.attributes[result[2]] = result[3]\n .trim()\n .substring(1, result[3].length - 1); }\n }\n }\n return {\n type: type,\n node: res,\n voidElement: voidElement\n };\n};\nvar stringToObj = function (html, options) {\n if (options === void 0) { options = {\n valueDiffing: true,\n caseSensitive: false\n }; }\n var result = [];\n var current;\n var level = -1;\n var arr = [];\n var inComponent = false, insideSvg = false;\n // handle text at top level\n if (html.indexOf(\"<\") !== 0) {\n var end = html.indexOf(\"<\");\n result.push({\n nodeName: \"#text\",\n data: end === -1 ? html : html.substring(0, end)\n });\n }\n html.replace(tagRE, function (tag, index) {\n var isOpen = tag.charAt(1) !== \"/\";\n var isComment = tag.startsWith(\"