CVE-2024-23825: Server-Side Request Forgery (SSRF) (CWE-918)
value: TablePress is a table plugin for Wordpress. For importing tables, TablePress makes external HTTP requests based on a URL that is provided by the user. That user input is filtered insufficiently, which makes it is possible to send requests to unintended network locations and receive responses. On sites in a cloud environment like AWS, an attacker can potentially make GET requests to the instance's metadata REST API. If the instance's configuration is insecure, this can lead to the exposure of internal data, including credentials. This vulnerability is fixed in 2.2.5.
CWE description: The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
CVSS v3 base score: 4.9
Published: 2024-01-30T17:15Z
Repository: https://github.com/TablePress/TablePress
Language: PHP
Files changed: .gitattributes, .github/workflows/wp-org-deploy.yml, admin/js/build/edit.asset.php, admin/js/build/edit.js, admin/js/edit.js, blocks/table/block.json, classes/class-import-phpspreadsheet.php, classes/class-import.php, classes/class-tablepress.php, classes/class-view.php, controllers/controller-admin.php, controllers/controller-admin_ajax.php, controllers/controller-frontend.php, libraries/freemius/includes/class-freemius.php, libraries/freemius/includes/class-fs-garbage-collector.php, libraries/freemius/start.php, models/model-table.php, package-lock.json, package.json, phpstan.neon.dist, readme.md, readme.txt, tablepress.php, tests/test-tablepress_import.php, views/view-about.php, views/view-edit.php, views/view-editor_button_thickbox.php, views/view-list.php
Commit date: 2024-01-27 21:56:59 +0100
Commit message: Finish TablePress 2.2.5.

Diff: diff --git a/.gitattributes b/.gitattributes
index 5510d34..a7a2c23 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2,33 +2,37 @@
 
 # Exclude these folders and files from release archives.
 /.git/ export-ignore
 /.github/ export-ignore
 /.phpstan/ export-ignore
+/.wordpress-org/ export-ignore
 /node_modules/ export-ignore
 /tests/ export-ignore
 /vendor/ export-ignore
 /.browserslistrc export-ignore
 /.editorconfig export-ignore
 /.eslintignore export-ignore
 /.eslintrc.js export-ignore
 /.gitattributes export-ignore
 /.gitignore export-ignore
+/.phpunit.result.cache export-ignore
 /.prettierignore export-ignore
 /.prettierrc.js export-ignore
 /.stylelintignore export-ignore
 /.stylelintrc.json export-ignore
+/.typos.toml export-ignore
 /composer.json export-ignore
 /composer.lock export-ignore
 /Gruntfile.js export-ignore
-/package.json export-ignore
 /package-lock.json export-ignore
+/package.json export-ignore
 /phpcompat.xml.dist export-ignore
 /phpcs.xml.dist export-ignore
 /phpstan.neon.dist export-ignore
 /phpunit.xml.dist export-ignore
 /readme.md export-ignore
+/rector.php export-ignore
 /webpack.config.js export-ignore
 
 # Set default behaviour, in case users don't have core.autocrlf set.
 * text=auto
 
diff --git a/.github/workflows/wp-org-deploy.yml b/.github/workflows/wp-org-deploy.yml
new file mode 100644
index 0000000..a29a289
--- /dev/null
+++ b/.github/workflows/wp-org-deploy.yml
@@ -0,0 +1,47 @@
+name: Deploy to wordpress.org Repository
+
+on:
+  # Deploy to wordpress.org when a production release is created.
+  release:
+    types: [ released ]
+  # Do a "dry run" (without comming to SVN) when the workflow is manually triggered.
+  workflow_dispatch:
+
+jobs:
+
+  deploy_to_wordpress_org:
+    name: Deploy to wordpress.org${{ github.event_name == 'workflow_dispatch' && ' (dry run)' || '' }}
+    if: github.repository == 'TablePress/TablePress'
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Checkout TablePress repository
+        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+
+      - name: WordPress Plugin Deploy
+        id: deploy
+        uses: 10up/action-wordpress-plugin-deploy@stable
+        with:
+          generate-zip: true
+          dry-run: ${{ github.event_name == 'workflow_dispatch' }}
+        env:
+          SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
+          SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
+          SLUG: ${{ vars.SLUG }}
+
+      - name: Get plugin version
+        id: get-version
+        if: ${{ github.event_name != 'workflow_dispatch' }}
+        run: |
+          echo "version=$(awk '/Stable tag: /{print $NF}' readme.txt)" >> $GITHUB_OUTPUT
+
+      - name: Upload release ZIP file
+        uses: actions/upload-release-asset@v1
+        if: ${{ github.event_name != 'workflow_dispatch' }}
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        with:
+          upload_url: ${{ github.event.release.upload_url }}
+          asset_path: ${{ steps.deploy.outputs.zip-path }}
+          asset_name: ${{ vars.SLUG }}.${{ steps.get-version.outputs.version }}.zip
+          asset_content_type: application/zip
diff --git a/admin/js/build/edit.asset.php b/admin/js/build/edit.asset.php
index ae8259d..b291cdc 100644
--- a/admin/js/build/edit.asset.php
+++ b/admin/js/build/edit.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('wp-hooks', 'wp-i18n', 'wp-url'), 'version' => 'cdf1475bc9e3883381b2');
+<?php return array('dependencies' => array('wp-hooks', 'wp-i18n', 'wp-url'), 'version' => 'aabe698a026e2cdb0743');
diff --git a/admin/js/build/edit.js b/admin/js/build/edit.js
index 13d0787..73c64e1 100644
--- a/admin/js/build/edit.js
+++ b/admin/js/build/edit.js
@@ -1 +1 @@
-!function(){"use strict";var e=window.wp.i18n,t=window.wp.hooks,s=window.wp.url;const o=e=>"#"===e[0]?document.getElementById(e.slice(1)):document.querySelectorAll(e);window.tp=window.tp||{},tp.made_changes=!1,tp.helpers=tp.helpers||{},tp.callbacks=tp.callbacks||{},tp.helpers.selection=tp.helpers.selection||{rows:[0],columns:[0]},tp.helpers.unsaved_changes=tp.helpers.unsaved_changes||{},tp.helpers.unsaved_changes.unload_dialog=function(e){e.preventDefault(),e.returnValue=""},tp.helpers.unsaved_changes.set=function(){tp.made_changes||(tp.made_changes=!0,window.addEventListener("beforeunload",tp.helpers.unsaved_changes.unload_dialog))},tp.helpers.unsaved_changes.unset=function(){tp.made_changes=!1,window.removeEventListener("beforeunload",tp.helpers.unsaved_changes.unload_dialog)},tp.helpers.options=tp.helpers.options||{},tp.helpers.options.load=function(){Object.keys(tp.table.options).forEach((function(e){if("last_editor"===e)return;if(""===(e=(0,t.applyFilters)("tablepress.optionsLoad",e)))return;let s=o(`#option-${e}`);s||(s=o(`#option-${e}-${tp.table.options[e]}`)),s&&(s instanceof HTMLInputElement&&"checkbox"===s.type?s.checked=tp.table.options[e]:s instanceof HTMLInputElement&&"radio"===s.type?s.checked=!0:s.value=tp.table.options[e])})),tp.table.options.use_datatables&&tp.helpers.editor.has_merged_cells()&&(tp.table.options.use_datatables=!1,o("#option-use_datatables").checked=!1),tp.helpers.options.check_dependencies()},tp.helpers.options.change=function(s){if(!s.target)return;const l=s.target.name||"";if(""===l)return;const a=s.target instanceof HTMLInputElement&&"checkbox"===s.target.type?"checked":"value";tp.table.options[l]=s.target[a],s.target instanceof HTMLInputElement&&"number"===s.target.type&&(tp.table.options[l]=parseInt(tp.table.options[l],10)),"use_datatables"===l&&tp.table.options.use_datatables&&tp.helpers.editor.has_merged_cells()&&(tp.table.options.use_datatables=!1,o("#option-use_datatables").checked=!1,window.alert((0,e.__)("You can not enable the Table Features for Site Visitors, because your table contains combined/merged cells.","tablepress"))),(0,t.doAction)("tablepress.optionsChange",l,a,s),tp.helpers.options.check_dependencies(),tp.helpers.unsaved_changes.set(),tp.editor.updateTable()},tp.helpers.options.check_dependencies=function(){o("#option-use_datatables").disabled=!tp.table.options.table_head,o("#notice-datatables-head-row").style.display=tp.table.options.table_head?"none":"block",o("#option-print_name_position").disabled=!tp.table.options.print_name,o("#option-print_description_position").disabled=!tp.table.options.print_description;const e=tp.table.options.use_datatables&&tp.table.options.table_head;o("#tablepress_edit-datatables-features").querySelectorAll(":scope input:not(#option-use_datatables), :scope textarea").forEach((t=>t.disabled=!e));const s=e&&tp.table.options.datatables_paginate;o("#option-datatables_lengthchange").disabled=!s,o("#option-datatables_paginate_entries").disabled=!s,(0,t.doAction)("tablepress.optionsCheckDependencies")},tp.helpers.options.validate_fields=function(){if(tp.table.options.datatables_paginate&&(isNaN(tp.table.options.datatables_paginate_entries)||tp.table.options.datatables_paginate_entries<1||tp.table.options.datatables_paginate_entries>9999)){window.alert((0,e.sprintf)((0,e.__)("The entered value in the “%1$s” field is invalid.","tablepress"),(0,e.__)("Pagination Entries","tablepress")));const t=o("#option-datatables_paginate_entries");return t.focus(),t.select(),!1}if(/[^A-Za-z0-9- _:]/.test(tp.table.options.extra_css_classes)){window.alert((0,e.sprintf)((0,e.__)("The entered value in the “%1$s” field is invalid.","tablepress"),(0,e.__)("Extra CSS Classes","tablepress")));const t=o("#option-extra_css_classes");return t.focus(),t.select(),!1}return(0,t.applyFilters)("tablepress.optionsValidateFields",!0)},tp.helpers.visibility=tp.helpers.visibility||{},tp.helpers.visibility.load=function(){const e=tp.table.visibility.rows.length,t=tp.table.visibility.columns.length,s={};for(let o=0;o<e;o++)if(1!==tp.table.visibility.rows[o])for(let e=0;e<t;e++){const t=jspreadsheet.getColumnNameFromId([e,o]);s[t]=s[t]||{},s[t].row_hidden=!0}for(let o=0;o<t;o++)if(1!==tp.table.visibility.columns[o])for(let t=0;t<e;t++){const e=jspreadsheet.getColumnNameFromId([o,t]);s[e]=s[e]||{},s[e].column_hidden=!0}return s},tp.helpers.visibility.update=function(){tp.table.visibility.rows=[];for(let e=0;e<tp.editor.options.data.length;e++)tp.table.visibility.rows[e]=1;tp.table.visibility.columns=[];for(let e=0;e<tp.editor.options.columns.length;e++)tp.table.visibility.columns[e]=1;Object.keys(tp.editor.options.meta).forEach((function(e){const t=jspreadsheet.getIdFromColumnName(e,!0);1===tp.table.visibility.rows[t[1]]&&tp.editor.options.meta[e].row_hidden&&(tp.table.visibility.rows[t[1]]=0),1===tp.table.visibility.columns[t[0]]&&tp.editor.options.meta[e].column_hidden&&(tp.table.visibility.columns[t[0]]=0)}))},tp.helpers.visibility.selection_contains=function(e,t){return tp.helpers.selection[e].some((s=>tp.table.visibility[e][s]===t))},tp.helpers.move_allowed=function(e,t){let s=tp.helpers.selection[e][0],o=0;return"down"!==t&&"right"!==t&&"bottom"!==t&&"last"!==t||(s=tp.helpers.selection[e][tp.helpers.selection[e].length-1],o="rows"===e?tp.editor.options.data.length-1:tp.editor.options.columns.length-1),o!==s},tp.helpers.cell_merge_allowed=function(t,s={}){const o="alert"===t;if(tp.table.options.table_head&&tp.table.options.use_datatables)return s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Enable Visitor Features","tablepress"),(0,e.__)("Table Features for Site Visitors","tablepress"))+" "+(0,e.__)("The Table Features for Site Visitors are not compatible with merged cells.","tablepress"),o&&window.alert(s.text),!1;const l=tp.helpers.selection.rows[0],a=tp.helpers.selection.rows[tp.helpers.selection.rows.length-1];if(tp.table.options.table_head&&0===l&&a>0)return s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Table Head Row","tablepress"),(0,e.__)("Table Options","tablepress")),o&&window.alert(s.text),!1;const n=tp.editor.options.data.length-1;return!(tp.table.options.table_foot&&n===a&&l<n&&(s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Table Foot Row","tablepress"),(0,e.__)("Table Options","tablepress")),o&&window.alert(s.text),1))},tp.helpers.editor=tp.helpers.editor||{},tp.helpers.editor.reselect=function(e,t){void 0===t&&(t=tp.editor),t.updateSelectionFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],tp.helpers.selection.columns[tp.helpers.selection.columns.length-1],tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.helpers.editor.has_merged_cells=function(){const e=tp.editor.options.data.length,t=tp.editor.options.columns.length;for(let s=1;s<e;s++)for(let e=1;e<t;e++)if("#rowspan#"===tp.editor.options.data[s][e]||"#colspan#"===tp.editor.options.data[s][e])return!0;return!1},tp.helpers.editor.sorting=function(e){return e=e?-1:1,function(t,s){return e*((e,t)=>{const s=/(^([+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|^0x[\da-fA-F]+$|\d+)/g,o=/^\s+|\s+$/g,l=/\s+/g,a=/^0x[0-9a-f]+$/i,n=/^0/,i=e.replace(o,"")||"",r=t.replace(o,"")||"",c=i.replace(s,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0"),p=r.replace(s,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0"),d=parseInt(i.match(a),16)||1!==c.length&&Date.parse(i),u=parseInt(r.match(a),16)||d&&r.match(/(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/)&&Date.parse(r)||null,b=(e,t)=>(!e.match(n)||1===t)&&parseFloat(e)||e.replace(l," ").replace(o,"")||0;if(u){if(d<u)return-1;if(d>u)return 1}for(let e=0,t=c.length,s=p.length,o=Math.max(t,s);e<o;e++){const o=b(c[e]||"",t),l=b(p[e]||"",s);if(isNaN(o)!==isNaN(l))return isNaN(o)?1:-1;if(/[^\x00-\x80]/.test(o+l)&&o.localeCompare){const e=o.localeCompare(l);return e/Math.abs(e)}if(o<l)return-1;if(o>l)return 1}return 0})(t[1],s[1])}},tp.callbacks.editor=tp.callbacks.editor||{},tp.callbacks.editor.onselection=function(e,t,s,o,l){tp.helpers.selection={rows:[],columns:[]};for(let e=s;e<=l;e++)tp.helpers.selection.rows.push(e);for(let e=t;e<=o;e++)tp.helpers.selection.columns.push(e)},tp.callbacks.editor.onupdatetable=function(e,t,s,o,l,a,n){const i=e.jspreadsheet.options.meta[n];if(t.classList.toggle("column-hidden",Boolean(i?.column_hidden)),0===s&&(t.parentNode.classList.toggle("row-hidden",Boolean(i?.row_hidden)),t.parentNode.classList.remove("head-row","foot-row"),o===e.jspreadsheet.rows.length-1)){const t=e.jspreadsheet.content.querySelectorAll(":scope tbody tr:not(.row-hidden)");1<t.length&&(tp.table.options.table_head&&t[0].classList.add("head-row"),tp.table.options.table_foot&&t[t.length-1].classList.add("foot-row"))}},tp.callbacks.editor.oninsertroc=function(e,t,s,o,l,a,n){const i="rows"===e,r=i?"column_hidden":"row_hidden",c="duplicate"===t,p=o+(n?l:0),d=i?tp.editor.options.columns.length:tp.editor.options.data.length,u={};for(let e=0;e<d;e++){const t=i?[e,p]:[p,e],s=tp.editor.options.meta[jspreadsheet.getColumnNameFromId(t)];s&&(c?u[e]=s:s[r]&&(u[e]=u[e]||{},u[e][r]=!0))}const b=Object.keys(u);if(!b.length)return;const h={};n||o++;for(let e=0;e<l;e++){const t=o+e;b.forEach((function(e){const s=i?[e,t]:[t,e];h[jspreadsheet.getColumnNameFromId(s)]=u[e]}))}tp.editor.setMeta(h),tp.editor.updateTable()},tp.callbacks.editor.onmove=function(){tp.helpers.editor.reselect(),tp.helpers.unsaved_changes.set()},tp.callbacks.editor.onsort=function(){tp.editor.updateTable(),tp.helpers.unsaved_changes.set()},tp.helpers.editor.insert_from_helper_textarea=function(){tp.editor.setValueFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],this.value)},tp.callbacks.insert_link={},tp.callbacks.insert_link.open_dialog=function(t=null){const s=o("#textarea-insert-helper");s.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]],t?(s.selectionStart=t.selectionStart,s.selectionEnd=t.selectionEnd):(s.selectionStart=s.value.length,s.selectionEnd=s.value.length);const l=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]);o("#link-modal-title").textContent=(0,e.sprintf)((0,e.__)("Insert Link into cell %1$s","tablepress"),l),wpLink.open("textarea-insert-helper"),jexcel.current=null},tp.callbacks.insert_image={},tp.callbacks.insert_image.open_dialog=function(t=null){const s=o("#textarea-insert-helper");s.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]],t?(s.selectionStart=t.selectionStart,s.selectionEnd=t.selectionEnd):(s.selectionStart=s.value.length,s.selectionEnd=s.value.length),wp.media.editor.open("textarea-insert-helper",{frame:"post",state:"insert",title:wp.media.view.l10n.addMedia,multiple:!0});const l=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]);document.querySelector("#media-frame-title h1").textContent=(0,e.sprintf)((0,e.__)("Add media to cell %1$s","tablepress"),l),jexcel.current=null},tp.callbacks.advanced_editor={},tp.callbacks.advanced_editor.$textarea=o("#advanced-editor-content"),tp.callbacks.advanced_editor.open_dialog=function(t=null){tp.callbacks.advanced_editor.$textarea.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]];const s=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]),l=(0,e.sprintf)((0,e.__)("Advanced Editor for cell %1$s","tablepress"),s);o("#advanced-editor-label").textContent=l,o("#link-modal-title").textContent=(0,e.sprintf)((0,e.__)("Insert Link into cell %1$s","tablepress"),s),jQuery("#advanced-editor").wpdialog({width:600,modal:!0,title:l,resizable:!1,closeOnEscape:!0,buttons:[{text:(0,e.__)("Cancel","tablepress"),class:"button button-cancel",click(){jQuery(this).wpdialog("close")}},{text:(0,e.__)("OK","tablepress"),class:"button button-primary button-ok",click:tp.callbacks.advanced_editor.confirm_save}]}),jexcel.current=null,t?(tp.callbacks.advanced_editor.$textarea.selectionStart=t.selectionStart,tp.callbacks.advanced_editor.$textarea.selectionEnd=t.selectionEnd):(tp.callbacks.advanced_editor.$textarea.selectionStart=tp.callbacks.advanced_editor.$textarea.value.length,tp.callbacks.advanced_editor.$textarea.selectionEnd=tp.callbacks.advanced_editor.$textarea.value.length),tp.callbacks.advanced_editor.$textarea.focus()},tp.callbacks.advanced_editor.confirm_save=function(){const e=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]];tp.callbacks.advanced_editor.$textarea.value!==e&&tp.editor.setValueFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],tp.callbacks.advanced_editor.$textarea.value),jQuery(this).wpdialog("close")},tp.callbacks.help_box={},tp.callbacks.help_box.open_dialog=function(t){const s=o(t.target.dataset.helpBox);jQuery(s).wpdialog({height:s.dataset.height,width:s.dataset.width,minWidth:260,modal:!0,closeOnEscape:!0,buttons:[{text:(0,e.__)("OK","tablepress"),class:"button button-ok",click(){jQuery(this).wpdialog("close")}}],open(){jQuery(this).next().find(".button-ok").trigger("focus")}})},tp.callbacks.table_preview={},tp.callbacks.table_preview.process=function(t){t.preventDefault();let l=o("#table-name").value;if(""===l.trim()&&(l=(0,e.__)("(no name)","tablepress")),tp.callbacks.table_preview.$dialog=jQuery("#table-preview").wpdialog({autoOpen:!1,width:window.innerWidth-80,height:window.innerHeight-80,modal:!0,title:(0,e.sprintf)((0,e.__)("Preview of table “%1$s” (ID %2$s)","tablepress"),l,tp.table.id),closeOnEscape:!0,buttons:[{text:(0,e.__)("OK","tablepress"),class:"button button-ok",click(){jQuery(this).wpdialog("close")}}]}),!tp.made_changes){const e=o("#table-preview-iframe");return e.src=t.target.href,e.removeAttribute("srcdoc"),void tp.callbacks.table_preview.$dialog.wpdialog("open")}tp.helpers.visibility.update();const a={action:"tablepress_preview_table",_ajax_nonce:tp.nonces.preview_table,tablepress:{id:tp.table.id,new_id:tp.table.new_id,name:o("#table-name").value,description:o("#table-description").value,data:JSON.stringify(tp.editor.options.data),options:JSON.stringify(tp.table.options),visibility:JSON.stringify(tp.table.visibility),number:{rows:tp.editor.options.data.length,columns:tp.editor.options.columns.length}}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-table-preview" class="spinner-table-preview spinner is-active" title="${(0,e.__)("The Table Preview is being loaded …","tablepress")}"/>`),o(".button-show-preview").forEach((e=>e.classList.add("disabled"))),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(a)}).then((e=>{if(!e.ok)throw new Error(`There was a problem with the server, HTTP response code ${e.status} (${e.statusText}).`);return e.json()})).then((e=>{if(null==e||"-1"===e||void 0===e.success)throw new Error("The JSON data returned from the server is unclear or incomplete.");if(!0!==e.success)throw new Error("The preview could not be loaded.");tp.callbacks.table_preview.success(e)})).catch((e=>tp.callbacks.table_preview.error(e.message))).finally((()=>{o("#spinner-table-preview").remove(),o(".button-show-preview").forEach((e=>e.classList.remove("disabled"))),document.body.classList.remove("wait")}))},tp.callbacks.table_preview.success=function(e){const t=o("#table-preview-iframe");t.src="",t.srcdoc=`<!DOCTYPE html><html><head>${e.head_html}</head><body>${e.body_html}</body></html>`,tp.callbacks.table_preview.$dialog.wpdialog("open")},tp.callbacks.table_preview.error=function(t){t=(0,e.__)("Attention: Unfortunately, an error occurred.","tablepress")+" "+t;const s=`show-preview-${Date.now()}`;o("#spinner-table-preview").parentNode.insertAdjacentHTML("afterend",`<div id="${s}" class="ajax-alert notice notice-error"><p>${t}</p></div>`);const l=o(`#${s}`);l.offsetWidth,l.style.opacity=0,l.addEventListener("transitionend",(()=>l.remove()))},tp.callbacks.save_changes={},tp.callbacks.save_changes.process=function(t){if(!tp.helpers.options.validate_fields())return;tp.helpers.visibility.update();const l={action:"tablepress_save_table",_ajax_nonce:tp.nonces.edit_table,tablepress:{id:tp.table.id,new_id:tp.table.new_id,name:o("#table-name").value,description:o("#table-description").value,data:JSON.stringify(tp.editor.options.data),options:JSON.stringify(tp.table.options),visibility:JSON.stringify(tp.table.visibility),number:{rows:tp.editor.options.data.length,columns:tp.editor.options.columns.length}}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-save-changes" class="spinner-save-changes spinner is-active" title="${(0,e.__)("Changes are being saved …","tablepress")}"/>`),o(".button-save-changes").forEach((e=>e.disabled=!0)),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(l)}).then((e=>{if(!e.ok)throw new Error(`There was a problem with the server, HTTP response code ${e.status} (${e.statusText}).`);return e.json()})).then((t=>{if(null==t||"-1"===t||void 0===t.success)throw new Error("The JSON data returned from the server is unclear or incomplete.");if(!0!==t.success){const s=(0,e.__)("These errors were encountered:","tablepress"),o=t.error_details?`</p><p>${s}</p><pre>${t.error_details}</pre><p>`:"";throw new Error(`The table could not be saved to the database properly.${o}`)}tp.callbacks.save_changes.success(t)})).catch((e=>tp.callbacks.save_changes.error(e.message))).finally((()=>{o("#spinner-save-changes").remove(),o(".button-save-changes").forEach((e=>e.disabled=!1)),document.body.classList.remove("wait")}))},tp.callbacks.save_changes.success=function(t){tp.table.id!==t.table_id&&window?.history?.pushState&&window.history.pushState("","",window.location.href.replace(/table_id=[0-9a-zA-Z-_]+/gi,`table_id=${t.table_id}`)),tp.table.id=t.table_id,tp.table.new_id=t.table_id,o("#table-id").value=t.table_id;const s=o("#table-information-shortcode");s&&(s.value=`[${tp.table.shortcode} id=${t.table_id} /]`),tp.nonces.edit_table=t.new_edit_nonce,tp.nonces.preview_table=t.new_preview_nonce,o(".button-show-preview").forEach((e=>{e.href=e.href.replace(/item=[a-zA-Z0-9_-]+/g,`item=${t.table_id}`).replace(/&_wpnonce=[a-z0-9]+/gi,`&_wpnonce=${t.new_preview_nonce}`)})),o("#last-modified").textContent=t.last_modified,o("#last-editor").textContent=t.last_editor,tp.helpers.unsaved_changes.unset();const l={};if(l.success_save=(0,e.__)("The table was saved successfully.","tablepress"),l.success_save_success_id_change=l.success_save+" "+(0,e.__)("The table ID was changed.","tablepress"),l.success_save_error_id_change=l.success_save+" "+(0,e.__)("The table ID could not be changed, probably because the new ID is already in use!","tablepress"),"success_save_error_id_change"===t.message&&t.error_details){const s=(0,e.__)("These errors were encountered:","tablepress");l.success_save_error_id_change+=`</p><p>${s}</p><pre>${t.error_details}</pre><p>`}const a=t.message.includes("error")?"error":"success";tp.callbacks.save_changes.after_saving_notice(a,l[t.message])},tp.callbacks.save_changes.error=function(t){t=(0,e.__)("Attention: Unfortunately, an error occurred.","tablepress")+" "+t,tp.callbacks.save_changes.after_saving_notice("error",t)},tp.callbacks.save_changes.after_saving_notice=function(e,t){const s=`save-changes-${Date.now()}`;o("#spinner-save-changes").parentNode.insertAdjacentHTML("afterend",`<div id="${s}" class="ajax-alert notice notice-${e}"><p>${t}</p></div>`);const l=o(`#${s}`);l.offsetWidth,l.style.opacity=0,l.addEventListener("transitionend",(()=>l.remove()))},tp.callbacks.screen_options={},tp.callbacks.screen_options.update=function(e){if(e.target)return"table_editor_line_clamp"===e.target.id?(tp.editor.el.style.setProperty("--table-editor-line-clamp",parseInt(e.target.value,10)),void tp.editor.updateCornerPosition()):"table_editor_column_width"===e.target.id?(tp.screen_options.table_editor_column_width=parseInt(e.target.value,10),tp.screen_options.table_editor_column_width=Math.max(tp.screen_options.table_editor_column_width,30),tp.screen_options.table_editor_column_width=Math.min(tp.screen_options.table_editor_column_width,9999),tp.editor.colgroup.forEach((e=>e.setAttribute("width",tp.screen_options.table_editor_column_width))),void tp.editor.updateCornerPosition()):void 0},tp.callbacks.screen_options.set_was_changed=function(e){e.target&&(e.target.was_changed=!0)},tp.callbacks.screen_options.save=function(t){if(!t.target)return;if(!t.target.was_changed)return;t.target.was_changed=!1;const l={action:"tablepress_save_screen_options",_ajax_nonce:tp.nonces.screen_options,tablepress:{[t.target.id]:parseInt(t.target.value,10)}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-save-changes" class="spinner-save-changes spinner is-active" title="${(0,e.__)("Changes are being saved …","tablepress")}"/>`),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(l)}).finally((()=>{o("#spinner-save-changes").remove(),document.body.classList.remove("wait")}))},tp.callbacks.table_id=tp.callbacks.table_id||{},tp.callbacks.table_id.sanitize=function(){this.value=this.value.replace(/[^0-9a-zA-Z-_]/g,"")},tp.callbacks.table_id.change=function(){if(""===this.value||"0"===this.value)return window.alert((0,e.__)("This table ID is invalid. Please enter a different table ID.","tablepress")),this.value=tp.table.new_id,this.focus(),void this.select();if(!window.confirm((0,e.__)("Do you really want to change the Table ID? All blocks and Shortcodes for this table in your posts and pages will have to be adjusted!","tablepress")))return void(this.value=tp.table.new_id);tp.table.new_id=this.value;const t=o("#table-information-shortcode");t&&(t.value=`[${tp.table.shortcode} id=${tp.table.new_id} /]`,t.focus(),t.select()),tp.helpers.unsaved_changes.set()},tp.callbacks.insert_duplicate=function(e,t,s="before"){const o="rows"===t,l=o?tp.editor.insertRow:tp.editor.insertColumn,a=o?tp.editor.getRowData:tp.editor.getColumnData,n="duplicate"===e;tp.editor.options[o?"oninsertrow":"oninsertcolumn"]=tp.callbacks.editor.oninsertroc.bind(null,t,e),tp.helpers.selection[t].forEach((function(e,t){const o=e+t,i=n?a(o):1;l(i,o,"before"===s)})),tp.helpers.unsaved_changes.set();const i=tp.helpers.selection[t].length;i>1&&tp.editor.updateSelectionFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],o?tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]:tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]+i,o?tp.helpers.selection.rows[tp.helpers.selection.rows.length-1]+i:tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.callbacks.remove=function(e){const t="rows"===e,s=t?tp.editor.options.columns.length:tp.editor.options.data.length,o=t?tp.editor.options.data.length-1:tp.editor.options.columns.length-1;if(tp.editor.options.meta&&tp.helpers.selection[e].forEach((function(e){for(let o=0;o<s;o++){const s=t?[o,e]:[e,o];delete tp.editor.options.meta[jspreadsheet.getColumnNameFromId(s)]}})),(t?tp.editor.deleteRow:tp.editor.deleteColumn)(tp.helpers.selection[e][0],tp.helpers.selection[e].length),tp.helpers.unsaved_changes.set(),o===tp.helpers.selection[e][tp.helpers.selection[e].length-1]){const e=t?tp.helpers.selection.columns[0]:tp.helpers.selection.columns[0]-1,s=t?tp.helpers.selection.rows[0]-1:tp.helpers.selection.rows[0];tp.editor.updateSelectionFromCoords(e,s,e,s)}},tp.callbacks.append=function(e,t){const s="rows"===e,o=s?tp.editor.insertRow:tp.editor.insertColumn;tp.editor.options[s?"oninsertrow":"oninsertcolumn"]=tp.callbacks.editor.oninsertroc.bind(null,e,"append"),o(t),tp.helpers.unsaved_changes.set()},tp.callbacks.move=function(e,t){const s="rows"===t;let o=tp.helpers.selection[t],l=-1;if("down"===e||"right"===e)o=o.slice().reverse(),l=1;else if("top"===e||"first"===e)l=-o[0];else if("bottom"===e||"last"===e){o=o.slice().reverse();const e="rows"===t?tp.editor.options.data.length-1:tp.editor.options.columns.length-1;l=e-o[0]}if(0===l)return;const a=s?tp.editor.moveRow:tp.editor.moveColumn;o.forEach((e=>a(e,e+l))),tp.helpers.unsaved_changes.set(),tp.editor.updateSelectionFromCoords(s?tp.helpers.selection.columns[0]:tp.helpers.selection.columns[0]+l,s?tp.helpers.selection.rows[0]+l:tp.helpers.selection.rows[0],s?tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]:tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]+l,s?tp.helpers.selection.rows[tp.helpers.selection.rows.length-1]+l:tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.callbacks.sort=function(e){tp.editor.orderBy(tp.helpers.selection.columns[0],"desc"===e)},tp.callbacks.hide_unhide=function(e,t){const s="rows"===t,o=s?"row_hidden":"column_hidden",l=s?tp.editor.options.columns.length:tp.editor.options.data.length,a="hide"===e,n={};tp.helpers.selection[t].forEach((function(e){for(let t=0;t<l;t++){const l=s?[t,e]:[e,t],i=jspreadsheet.getColumnNameFromId(l);n[i]={},n[i][o]=a}})),tp.editor.setMeta(n),tp.helpers.unsaved_changes.set(),tp.editor.updateTable()},tp.callbacks.merge_cells=function(){const e=tp.helpers.selection.columns[0],t=tp.helpers.selection.rows[0],s=tp.helpers.selection.columns.length,o=tp.helpers.selection.rows.length;for(let s=1;s<o;s++)tp.editor.setValueFromCoords(e,t+s,"#rowspan#");for(let o=1;o<s;o++)tp.editor.setValueFromCoords(e+o,t,"#colspan#");for(let l=1;l<o;l++)for(let o=1;o<s;o++)tp.editor.setValueFromCoords(e+o,t+l,"#span#");tp.helpers.unsaved_changes.set()},tp.callbacks.keyboard_shortcuts=function(e){let t="",s="",l="";if((e.ctrlKey||e.metaKey)&&(80===e.keyCode?t="show-preview":83===e.keyCode?t="save-changes":76===e.keyCode?t="insert_link":73===e.keyCode?t="insert_image":69===e.keyCode?t="advanced_editor":e.shiftKey&&e.altKey&&38===e.keyCode?(t="move",s="top",l="rows"):e.shiftKey&&e.altKey&&40===e.keyCode?(t="move",s="bottom",l="rows"):e.shiftKey&&e.altKey&&37===e.keyCode?(t="move",s="first",l="columns"):e.shiftKey&&e.altKey&&39===e.keyCode?(t="move",s="last",l="columns"):e.shiftKey&&38===e.keyCode?(t="move",s="up",l="rows"):e.shiftKey&&40===e.keyCode?(t="move",s="down",l="rows"):e.shiftKey&&37===e.keyCode?(t="move",s="left",l="columns"):e.shiftKey&&39===e.keyCode&&(t="move",s="right",l="columns")),"save-changes"===t||"show-preview"===t)document.activeElement.blur(),document.querySelector(`#tablepress_edit-buttons-2-submit .button-${t}`).click(),e.preventDefault();else if("insert_link"===t||"insert_image"===t||"advanced_editor"===t){if(o("#table-editor").contains(document.activeElement)){const e="TEXTAREA"===document.activeElement.tagName?document.activeElement:null;tp.callbacks[t].open_dialog(e)}e.preventDefault()}else"move"===t&&(o("#table-editor").contains(document.activeElement)&&"TEXTAREA"!==document.activeElement.tagName&&tp.helpers.move_allowed(l,s)&&tp.callbacks.move(s,l),e.stopImmediatePropagation())},tp.editor=jspreadsheet(o("#table-editor"),{data:tp.table.data,meta:tp.helpers.visibility.load(),wordWrap:!0,rowDrag:!0,rowResize:!0,columnSorting:!0,columnDrag:!0,columnResize:!0,defaultColWidth:tp.screen_options.table_editor_column_width,defaultColAlign:"left",parseFormulas:!1,allowExport:!1,allowComments:!1,allowManualInsertRow:!1,allowManualInsertColumn:!1,about:!1,secureFormulas:!1,detachForUpdates:!0,onselection:tp.callbacks.editor.onselection,updateTable:tp.callbacks.editor.onupdatetable,contextMenu:t=>{const s=tp.editor.options.data.length,o=tp.editor.options.columns.length,l=tp.helpers.selection.rows.length,a=tp.helpers.selection.columns.length,n=window?.navigator?.platform?.includes("Mac"),i=n?(0,e._x)("⌘","keyboard shortcut modifier key on a Mac keyboard","tablepress"):(0,e._x)("Ctrl+","keyboard shortcut modifier key on a non-Mac keyboard","tablepress"),r=n?(0,e._x)("⌥","keyboard shortcut option key on a Mac keyboard","tablepress"):(0,e._x)("Alt+","keyboard shortcut Alt key on a non-Mac keyboard","tablepress"),c={text:""};return tp.helpers.visibility.update(),[{title:(0,e.__)("Undo","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sZ","keyboard shortcut for Undo","tablepress"),i),onclick:t.undo,disabled:-1===t.historyIndex},{title:(0,e.__)("Redo","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sY","keyboard shortcut for Redo","tablepress"),i),onclick:t.redo,disabled:t.historyIndex===t.history.length-1},{type:"divisor"},{title:(0,e.__)("Cut","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sX","keyboard shortcut for Cut","tablepress"),i),onclick(){if("TEXTAREA"===document.activeElement.tagName&&document.activeElement.selectionStart!==document.activeElement.selectionEnd){document.execCommand("copy");const e=document.activeElement.selectionStart;document.activeElement.value=document.activeElement.value.slice(0,document.activeElement.selectionStart)+document.activeElement.value.slice(document.activeElement.selectionEnd),document.activeElement.selectionEnd=e}else t.copy(!0),t.setValue(t.highlighted,"")}},{title:(0,e.__)("Copy","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sC","keyboard shortcut for Copy","tablepress"),i),onclick(){"TEXTAREA"===document.activeElement.tagName&&document.activeElement.selectionStart!==document.activeElement.selectionEnd?document.execCommand("copy"):t.copy(!0)}},{title:(0,e.__)("Paste","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sV","keyboard shortcut for Paste","tablepress"),i),onclick(){"TEXTAREA"===document.activeElement.tagName?window.navigator.clipboard.readText().then((e=>{if(e){const t=document.activeElement.selectionStart+e.length;document.activeElement.value=document.activeElement.value.slice(0,document.activeElement.selectionStart)+e+document.activeElement.value.slice(document.activeElement.selectionEnd),document.activeElement.selectionEnd=t}})):t.selectedCell&&window.navigator.clipboard.readText().then((e=>{e&&t.paste(t.selectedCell[0],t.selectedCell[1],e)}))},disabled:!window?.navigator?.clipboard?.readText,tooltip:window?.navigator?.clipboard?.readText?"":(0,e.__)("Your browser does not allow pasting via the context menu. Use the keyboard shortcut instead.","tablepress")},{type:"divisor"},{title:(0,e.__)("Insert Link","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sL","keyboard shortcut for Insert Link","tablepress"),i),onclick:tp.callbacks.insert_link.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{title:(0,e.__)("Insert Image","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sI","keyboard shortcut for Insert Image","tablepress"),i),onclick:tp.callbacks.insert_image.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{title:(0,e.__)("Advanced Editor","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sE","keyboard shortcut for Advanced Editor","tablepress"),i),onclick:tp.callbacks.advanced_editor.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{type:"divisor"},{title:(0,e.__)("Duplicate …","tablepress"),submenu:[{title:(0,e._n)("Duplicate row","Duplicate rows",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"duplicate","rows")},{title:(0,e._n)("Duplicate column","Duplicate columns",a,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"duplicate","columns")}]},{title:(0,e.__)("Insert …","tablepress"),submenu:[{title:(0,e._n)("Insert row above","Insert rows above",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","rows","before")},{title:(0,e._n)("Insert row below","Insert rows below",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","rows","after")},{title:(0,e._n)("Insert column on the left","Insert columns on the left",a,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","columns","before")},{title:(0,e._n)("Insert column on the right","Insert columns on the right",a,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","columns","after")}]},{title:(0,e.__)("Append …","tablepress"),submenu:[{title:(0,e.__)("Append row","tablepress"),onclick:tp.callbacks.append.bind(null,"rows",1)},{title:(0,e.__)("Append column","tablepress"),onclick:tp.callbacks.append.bind(null,"columns",1)}]},{title:(0,e.__)("Delete …","tablepress"),submenu:[{title:(0,e._n)("Delete row","Delete rows",l,"tablepress"),onclick:tp.callbacks.remove.bind(null,"rows"),disabled:s===l,tooltip:s===l?(0,e.__)("This option is disabled.","tablepress")+" "+(0,e.__)("You can not delete all table rows!","tablepress"):""},{title:(0,e._n)("Delete column","Delete columns",a,"tablepress"),onclick:tp.callbacks.remove.bind(null,"columns"),disabled:o===a,tooltip:o===a?(0,e.__)("This option is disabled.","tablepress")+" "+(0,e.__)("You can not delete all table columns!","tablepress"):""}]},{type:"divisor"},{title:(0,e.__)("Move …","tablepress"),submenu:[{title:(0,e._n)("Move row up","Move rows up",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧↑","keyboard shortcut for Move up","tablepress"),i),onclick:tp.callbacks.move.bind(null,"up","rows"),disabled:!tp.helpers.move_allowed("rows","up")},{title:(0,e._n)("Move row down","Move rows down",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧↓","keyboard shortcut for Move down","tablepress"),i),onclick:tp.callbacks.move.bind(null,"down","rows"),disabled:!tp.helpers.move_allowed("rows","down")},{title:(0,e._n)("Move column left","Move columns left",a,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧←","keyboard shortcut for Move left","tablepress"),i),onclick:tp.callbacks.move.bind(null,"left","columns"),disabled:!tp.helpers.move_allowed("columns","left")},{title:(0,e._n)("Move column right","Move columns right",a,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧→","keyboard shortcut for Move right","tablepress"),i),onclick:tp.callbacks.move.bind(null,"right","columns"),disabled:!tp.helpers.move_allowed("columns","right")},{type:"divisor"},{title:(0,e._n)("Move row to the top","Move rows to the top",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧↑","keyboard shortcut for Move to the top","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"top","rows"),disabled:!tp.helpers.move_allowed("rows","top")},{title:(0,e._n)("Move row to the bottom","Move rows to the bottom",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧↓","keyboard shortcut for Move to the bottom","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"bottom","rows"),disabled:!tp.helpers.move_allowed("rows","bottom")},{title:(0,e._n)("Move column to first","Move columns to first",a,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧←","keyboard shortcut for Move to first","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"first","columns"),disabled:!tp.helpers.move_allowed("columns","first")},{title:(0,e._n)("Move column to last","Move columns to last",a,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧→","keyboard shortcut for Move to last","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"last","columns"),disabled:!tp.helpers.move_allowed("columns","last")}]},{title:(0,e.__)("Sort by column …","tablepress"),submenu:[{title:(0,e.__)("Sort by column ascending","tablepress"),onclick:tp.callbacks.sort.bind(null,"asc"),disabled:1!==a,tooltip:1!==a?(0,e.__)("This option is disabled because more than one column was selected.","tablepress"):""},{title:(0,e.__)("Sort by column descending","tablepress"),onclick:tp.callbacks.sort.bind(null,"desc"),disabled:1!==a,tooltip:1!==a?(0,e.__)("This option is disabled because more than one column was selected.","tablepress"):""}]},{type:"divisor"},{title:(0,e.__)("Hide/Show …","tablepress"),submenu:[{title:(0,e._n)("Hide row","Hide rows",l,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"hide","rows"),disabled:!tp.helpers.visibility.selection_contains("rows",1),tooltip:tp.helpers.visibility.selection_contains("rows",1)?"":(0,e.__)("This option is disabled because no visible rows were selected.","tablepress")},{title:(0,e._n)("Hide column","Hide columns",a,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"hide","columns"),disabled:!tp.helpers.visibility.selection_contains("columns",1),tooltip:tp.helpers.visibility.selection_contains("columns",1)?"":(0,e.__)("This option is disabled because no visible columns were selected.","tablepress")},{title:(0,e._n)("Show row","Show rows",l,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"unhide","rows"),disabled:!tp.helpers.visibility.selection_contains("rows",0),tooltip:tp.helpers.visibility.selection_contains("rows",0)?"":(0,e.__)("This option is disabled because no hidden rows were selected.","tablepress")},{title:(0,e._n)("Show column","Show columns",a,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"unhide","columns"),disabled:!tp.helpers.visibility.selection_contains("columns",0),tooltip:tp.helpers.visibility.selection_contains("columns",0)?"":(0,e.__)("This option is disabled because no hidden columns were selected.","tablepress")}]},{type:"divisor"},{title:(0,e.__)("Combine/Merge cells","tablepress"),onclick:tp.callbacks.merge_cells,disabled:1===l&&1===a||!tp.helpers.cell_merge_allowed("no-alert"),tooltip:1===l&&1===a||!tp.helpers.cell_merge_allowed("no-alert",c)?(0,e.__)("This option is disabled.","tablepress")+" "+c.text:""}]},sorting:tp.helpers.editor.sorting,onmoverow:tp.callbacks.editor.onmove,onmovecolumn:tp.callbacks.editor.onmove,onblur:tp.helpers.editor.reselect,onload:tp.helpers.editor.reselect,onchange:tp.helpers.unsaved_changes.set,onsort:tp.callbacks.editor.onsort}),tp.helpers.options.load(),o("#tablepress-page").addEventListener("click",(e=>{e.target&&(e.target.matches(".button-show-preview")?tp.callbacks.table_preview.process(e):e.target.matches(".button-save-changes")?tp.callbacks.save_changes.process(e):e.target.matches(".button-show-help-box")&&tp.callbacks.help_box.open_dialog(e))})),o("#tablepress-manipulation-controls").addEventListener("click",(t=>{if(t.target)if(t.target.matches(".button-append")){const s=t.target.dataset.type,l=o(`#${s}-append-number`),a=parseInt(l.value,10);if(isNaN(a)||a<1||a>99999){const s="rows"===t.target.dataset.type?(0,e.__)("The value for the number of rows is invalid!","tablepress"):(0,e.__)("The value for the number of columns is invalid!","tablepress");return window.alert(s),l.focus(),void l.select()}tp.callbacks.append(s,a)}else if("button-insert-link"!==t.target.id)if("button-insert-image"!==t.target.id)if("button-advanced-editor"!==t.target.id)if(t.target.matches(".button-insert-duplicate"))tp.callbacks.insert_duplicate(t.target.dataset.action,t.target.dataset.type);else{if(t.target.matches(".button-move"))return tp.helpers.move_allowed(t.target.dataset.type,t.target.dataset.direction)?void tp.callbacks.move(t.target.dataset.direction,t.target.dataset.type):void window.alert((0,e.__)("You can not do this move, because you reached the border of the table.","tablepress"));if(t.target.matches(".button-remove")){const s="rows"===t.target.dataset.type;if((s?tp.editor.options.data.length:tp.editor.options.columns.length)===tp.helpers.selection[t.target.dataset.type].length){const t=s?(0,e.__)("You can not delete all table rows!","tablepress"):(0,e.__)("You can not delete all table columns!","tablepress");return void window.alert(t)}tp.callbacks.remove(t.target.dataset.type)}else t.target.matches(".button-merge-unmerge")?tp.helpers.cell_merge_allowed("alert")&&tp.callbacks.merge_cells():t.target.matches(".button-hide-unhide")&&tp.callbacks.hide_unhide(t.target.dataset.action,t.target.dataset.type)}else tp.callbacks.advanced_editor.open_dialog();else tp.callbacks.insert_image.open_dialog();else tp.callbacks.insert_link.open_dialog()}));const l=o("#table-id");l.addEventListener("input",tp.callbacks.table_id.sanitize),l.addEventListener("change",tp.callbacks.table_id.change);const a=o("#table-information-shortcode");a&&a.addEventListener("focus",(function(){this.select()})),jQuery("#textarea-insert-helper").on("change",tp.helpers.editor.insert_from_helper_textarea),["#table-name","#table-description"].forEach((e=>o(e).addEventListener("change",tp.helpers.unsaved_changes.set))),(0,t.applyFilters)("tablepress.optionsMetaBoxes",["#tablepress_edit-table-options","#tablepress_edit-datatables-features"]).forEach((e=>o(e).addEventListener("change",tp.helpers.options.change))),document.querySelectorAll("#tablepress-body .button-module-help").forEach((e=>e.closest(".postbox").querySelector(".handle-actions").prepend(e)));const n=o("#tablepress-screen-options");n.addEventListener("input",tp.callbacks.screen_options.update),n.addEventListener("change",tp.callbacks.screen_options.set_was_changed),n.addEventListener("focusout",tp.callbacks.screen_options.save),window.addEventListener("keydown",tp.callbacks.keyboard_shortcuts,!0);const i=window?.navigator?.platform?.includes("Mac")?(0,e._x)("⌘","keyboard shortcut modifier key on a Mac keyboard","tablepress"):(0,e._x)("Ctrl+","keyboard shortcut modifier key on a non-Mac keyboard","tablepress");document.querySelectorAll(".button[data-shortcut]").forEach((t=>{const s=(0,e.sprintf)(t.dataset.shortcut,i);t.title=(0,e.sprintf)((0,e.__)("Keyboard Shortcut: %s","tablepress"),s)})),jQuery((function(){jQuery("#wp-link").on("focus","input",(function(e){e.stopPropagation()})),jQuery("body").on("focus",".media-modal .media-frame-content input, .media-modal .media-frame-content textarea",(function(e){e.stopPropagation()}))}))}();
\ No newline at end of file
+!function(){"use strict";var e=window.wp.i18n,t=window.wp.hooks,s=window.wp.url;const o=e=>"#"===e[0]?document.getElementById(e.slice(1)):document.querySelectorAll(e);window.tp=window.tp||{},tp.made_changes=!1,tp.helpers=tp.helpers||{},tp.callbacks=tp.callbacks||{},tp.helpers.selection=tp.helpers.selection||{rows:[0],columns:[0]},tp.helpers.unsaved_changes=tp.helpers.unsaved_changes||{},tp.helpers.unsaved_changes.unload_dialog=function(e){e.preventDefault(),e.returnValue=""},tp.helpers.unsaved_changes.set=function(){tp.made_changes||(tp.made_changes=!0,window.addEventListener("beforeunload",tp.helpers.unsaved_changes.unload_dialog))},tp.helpers.unsaved_changes.unset=function(){tp.made_changes=!1,window.removeEventListener("beforeunload",tp.helpers.unsaved_changes.unload_dialog)},tp.helpers.options=tp.helpers.options||{},tp.helpers.options.load=function(){Object.keys(tp.table.options).forEach((function(e){if("last_editor"===e)return;if(""===(e=(0,t.applyFilters)("tablepress.optionsLoad",e)))return;let s=o(`#option-${e}`);s||(s=o(`#option-${e}-${tp.table.options[e]}`)),s&&(s instanceof HTMLInputElement&&"checkbox"===s.type?s.checked=tp.table.options[e]:s instanceof HTMLInputElement&&"radio"===s.type?s.checked=!0:s.value=tp.table.options[e])})),tp.table.options.use_datatables&&tp.helpers.editor.has_merged_cells()&&(tp.table.options.use_datatables=!1,o("#option-use_datatables").checked=!1),tp.helpers.options.check_dependencies()},tp.helpers.options.change=function(s){if(!s.target)return;const l=s.target.name||"";if(""===l)return;const n=s.target instanceof HTMLInputElement&&"checkbox"===s.target.type?"checked":"value";tp.table.options[l]=s.target[n],s.target instanceof HTMLInputElement&&"number"===s.target.type&&(tp.table.options[l]=parseInt(tp.table.options[l],10)),"use_datatables"===l&&tp.table.options.use_datatables&&tp.helpers.editor.has_merged_cells()&&(tp.table.options.use_datatables=!1,o("#option-use_datatables").checked=!1,window.alert((0,e.__)("You can not enable the Table Features for Site Visitors, because your table contains combined/merged cells.","tablepress"))),(0,t.doAction)("tablepress.optionsChange",l,n,s),tp.helpers.options.check_dependencies(),tp.helpers.unsaved_changes.set(),tp.editor.updateTable()},tp.helpers.options.check_dependencies=function(){o("#option-use_datatables").disabled=!tp.table.options.table_head,o("#notice-datatables-head-row").style.display=tp.table.options.table_head?"none":"block",o("#option-print_name_position").disabled=!tp.table.options.print_name,o("#option-print_description_position").disabled=!tp.table.options.print_description;const e=tp.table.options.use_datatables&&tp.table.options.table_head;o("#tablepress_edit-datatables-features").querySelectorAll(":scope input:not(#option-use_datatables), :scope textarea").forEach((t=>t.disabled=!e));const s=e&&tp.table.options.datatables_paginate;o("#option-datatables_lengthchange").disabled=!s,o("#option-datatables_paginate_entries").disabled=!s,(0,t.doAction)("tablepress.optionsCheckDependencies")},tp.helpers.options.validate_fields=function(){if(tp.table.options.datatables_paginate&&(isNaN(tp.table.options.datatables_paginate_entries)||tp.table.options.datatables_paginate_entries<1||tp.table.options.datatables_paginate_entries>9999)){window.alert((0,e.sprintf)((0,e.__)("The entered value in the “%1$s” field is invalid.","tablepress"),(0,e.__)("Pagination Entries","tablepress")));const t=o("#option-datatables_paginate_entries");return t.focus(),t.select(),!1}if(/[^A-Za-z0-9- _:]/.test(tp.table.options.extra_css_classes)){window.alert((0,e.sprintf)((0,e.__)("The entered value in the “%1$s” field is invalid.","tablepress"),(0,e.__)("Extra CSS Classes","tablepress")));const t=o("#option-extra_css_classes");return t.focus(),t.select(),!1}return(0,t.applyFilters)("tablepress.optionsValidateFields",!0)},tp.helpers.visibility=tp.helpers.visibility||{},tp.helpers.visibility.load=function(){const e=tp.table.visibility.rows.length,t=tp.table.visibility.columns.length,s={};for(let o=0;o<e;o++)if(1!==tp.table.visibility.rows[o])for(let e=0;e<t;e++){const t=jspreadsheet.getColumnNameFromId([e,o]);s[t]=s[t]||{},s[t].row_hidden=!0}for(let o=0;o<t;o++)if(1!==tp.table.visibility.columns[o])for(let t=0;t<e;t++){const e=jspreadsheet.getColumnNameFromId([o,t]);s[e]=s[e]||{},s[e].column_hidden=!0}return s},tp.helpers.visibility.update=function(){tp.table.visibility.rows=[];for(let e=0;e<tp.editor.options.data.length;e++)tp.table.visibility.rows[e]=1;tp.table.visibility.columns=[];for(let e=0;e<tp.editor.options.columns.length;e++)tp.table.visibility.columns[e]=1;Object.keys(tp.editor.options.meta).forEach((function(e){const t=jspreadsheet.getIdFromColumnName(e,!0);1===tp.table.visibility.rows[t[1]]&&tp.editor.options.meta[e].row_hidden&&(tp.table.visibility.rows[t[1]]=0),1===tp.table.visibility.columns[t[0]]&&tp.editor.options.meta[e].column_hidden&&(tp.table.visibility.columns[t[0]]=0)}))},tp.helpers.visibility.selection_contains=function(e,t){return tp.helpers.selection[e].some((s=>tp.table.visibility[e][s]===t))},tp.helpers.move_allowed=function(e,t){let s=tp.helpers.selection[e][0],o=0;return"down"!==t&&"right"!==t&&"bottom"!==t&&"last"!==t||(s=tp.helpers.selection[e][tp.helpers.selection[e].length-1],o="rows"===e?tp.editor.options.data.length-1:tp.editor.options.columns.length-1),o!==s},tp.helpers.cell_merge_allowed=function(t,s={}){const o="alert"===t;if(tp.table.options.table_head&&tp.table.options.use_datatables)return s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Enable Visitor Features","tablepress"),(0,e.__)("Table Features for Site Visitors","tablepress"))+" "+(0,e.__)("The Table Features for Site Visitors are not compatible with merged cells.","tablepress"),o&&window.alert(s.text),!1;const l=tp.helpers.selection.rows[0],n=tp.helpers.selection.rows[tp.helpers.selection.rows.length-1];if(tp.table.options.table_head&&0===l&&n>0)return s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Table Head Row","tablepress"),(0,e.__)("Table Options","tablepress")),o&&window.alert(s.text),!1;const a=tp.editor.options.data.length-1;return!(tp.table.options.table_foot&&a===n&&l<a&&(s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Table Foot Row","tablepress"),(0,e.__)("Table Options","tablepress")),o&&window.alert(s.text),1))},tp.helpers.editor=tp.helpers.editor||{},tp.helpers.editor.reselect=function(e,t){void 0===t&&(t=tp.editor),t.updateSelectionFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],tp.helpers.selection.columns[tp.helpers.selection.columns.length-1],tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.helpers.editor.has_merged_cells=function(){const e=tp.editor.options.data.length,t=tp.editor.options.columns.length;for(let s=1;s<e;s++)for(let e=1;e<t;e++)if("#rowspan#"===tp.editor.options.data[s][e]||"#colspan#"===tp.editor.options.data[s][e])return!0;return!1},tp.helpers.editor.sorting=function(e){return e=e?-1:1,function(t,s){return e*((e,t)=>{const s=/(^([+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|^0x[\da-fA-F]+$|\d+)/g,o=/^\s+|\s+$/g,l=/\s+/g,n=/^0x[0-9a-f]+$/i,a=/^0/,i=e.replace(o,"")||"",r=t.replace(o,"")||"",c=i.replace(s,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0"),p=r.replace(s,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0"),d=parseInt(i.match(n),16)||1!==c.length&&Date.parse(i),b=parseInt(r.match(n),16)||d&&r.match(/(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/)&&Date.parse(r)||null,u=(e,t)=>(!e.match(a)||1===t)&&parseFloat(e)||e.replace(l," ").replace(o,"")||0;if(b){if(d<b)return-1;if(d>b)return 1}for(let e=0,t=c.length,s=p.length,o=Math.max(t,s);e<o;e++){const o=u(c[e]||"",t),l=u(p[e]||"",s);if(isNaN(o)!==isNaN(l))return isNaN(o)?1:-1;if(/[^\x00-\x80]/.test(o+l)&&o.localeCompare){const e=o.localeCompare(l);return e/Math.abs(e)}if(o<l)return-1;if(o>l)return 1}return 0})(t[1],s[1])}},tp.callbacks.editor=tp.callbacks.editor||{},tp.callbacks.editor.onselection=function(e,t,s,o,l){tp.helpers.selection={rows:[],columns:[]};for(let e=s;e<=l;e++)tp.helpers.selection.rows.push(e);for(let e=t;e<=o;e++)tp.helpers.selection.columns.push(e)},tp.callbacks.editor.onupdatetable=function(e,t,s,o,l,n,a){const i=e.jspreadsheet.options.meta[a];if(t.classList.toggle("column-hidden",Boolean(i?.column_hidden)),0===s&&(t.parentNode.classList.toggle("row-hidden",Boolean(i?.row_hidden)),t.parentNode.classList.remove("head-row","foot-row"),o===e.jspreadsheet.rows.length-1)){const t=e.jspreadsheet.content.querySelectorAll(":scope tbody tr:not(.row-hidden)");1<t.length&&(tp.table.options.table_head&&t[0].classList.add("head-row"),tp.table.options.table_foot&&t[t.length-1].classList.add("foot-row"))}},tp.callbacks.editor.oninsertroc=function(e,t,s,o,l,n,a){const i="rows"===e,r=i?"column_hidden":"row_hidden",c="duplicate"===t,p=o+(a?l:0),d=i?tp.editor.options.columns.length:tp.editor.options.data.length,b={};for(let e=0;e<d;e++){const t=i?[e,p]:[p,e],s=tp.editor.options.meta[jspreadsheet.getColumnNameFromId(t)];s&&(c?b[e]=s:s[r]&&(b[e]=b[e]||{},b[e][r]=!0))}const u=Object.keys(b);if(!u.length)return;const h={};a||o++;for(let e=0;e<l;e++){const t=o+e;u.forEach((function(e){const s=i?[e,t]:[t,e];h[jspreadsheet.getColumnNameFromId(s)]=b[e]}))}tp.editor.setMeta(h),tp.editor.updateTable()},tp.callbacks.editor.onmove=function(){tp.helpers.editor.reselect(),tp.helpers.unsaved_changes.set()},tp.callbacks.editor.onsort=function(){tp.editor.updateTable(),tp.helpers.unsaved_changes.set()},tp.helpers.editor.insert_from_helper_textarea=function(){tp.editor.setValueFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],this.value)},tp.callbacks.insert_link={},tp.callbacks.insert_link.open_dialog=function(t=null){const s=o("#textarea-insert-helper");s.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]],t?(s.selectionStart=t.selectionStart,s.selectionEnd=t.selectionEnd):(s.selectionStart=s.value.length,s.selectionEnd=s.value.length);const l=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]);o("#link-modal-title").textContent=(0,e.sprintf)((0,e.__)("Insert Link into cell %1$s","tablepress"),l),wpLink.open("textarea-insert-helper"),jexcel.current=null},tp.callbacks.insert_image={},tp.callbacks.insert_image.open_dialog=function(t=null){const s=o("#textarea-insert-helper");s.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]],t?(s.selectionStart=t.selectionStart,s.selectionEnd=t.selectionEnd):(s.selectionStart=s.value.length,s.selectionEnd=s.value.length),wp.media.editor.open("textarea-insert-helper",{frame:"post",state:"insert",title:wp.media.view.l10n.addMedia,multiple:!0});const l=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]);document.querySelector("#media-frame-title h1").textContent=(0,e.sprintf)((0,e.__)("Add media to cell %1$s","tablepress"),l),jexcel.current=null},tp.callbacks.advanced_editor={},tp.callbacks.advanced_editor.$textarea=o("#advanced-editor-content"),tp.callbacks.advanced_editor.open_dialog=function(t=null){tp.callbacks.advanced_editor.$textarea.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]];const s=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]),l=(0,e.sprintf)((0,e.__)("Advanced Editor for cell %1$s","tablepress"),s);o("#advanced-editor-label").textContent=l,o("#link-modal-title").textContent=(0,e.sprintf)((0,e.__)("Insert Link into cell %1$s","tablepress"),s),jQuery("#advanced-editor").wpdialog({width:600,modal:!0,title:l,resizable:!1,closeOnEscape:!0,buttons:[{text:(0,e.__)("Cancel","tablepress"),class:"button button-cancel",click(){jQuery(this).wpdialog("close")}},{text:(0,e.__)("OK","tablepress"),class:"button button-primary button-ok",click:tp.callbacks.advanced_editor.confirm_save}]}),jexcel.current=null,t?(tp.callbacks.advanced_editor.$textarea.selectionStart=t.selectionStart,tp.callbacks.advanced_editor.$textarea.selectionEnd=t.selectionEnd):(tp.callbacks.advanced_editor.$textarea.selectionStart=tp.callbacks.advanced_editor.$textarea.value.length,tp.callbacks.advanced_editor.$textarea.selectionEnd=tp.callbacks.advanced_editor.$textarea.value.length),tp.callbacks.advanced_editor.$textarea.focus()},tp.callbacks.advanced_editor.confirm_save=function(){const e=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]];tp.callbacks.advanced_editor.$textarea.value!==e&&tp.editor.setValueFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],tp.callbacks.advanced_editor.$textarea.value),jQuery(this).wpdialog("close")},tp.callbacks.help_box={},tp.callbacks.help_box.open_dialog=function(t){const s=o(t.target.dataset.helpBox);jQuery(s).wpdialog({height:s.dataset.height,width:s.dataset.width,minWidth:260,modal:!0,closeOnEscape:!0,buttons:[{text:(0,e.__)("OK","tablepress"),class:"button button-ok",click(){jQuery(this).wpdialog("close")}}],open(){jQuery(this).next().find(".button-ok").trigger("focus")}})},tp.callbacks.table_preview={},tp.callbacks.table_preview.process=function(t){t.preventDefault();let l=o("#table-name").value;if(""===l.trim()&&(l=(0,e.__)("(no name)","tablepress")),tp.callbacks.table_preview.$dialog=jQuery("#table-preview").wpdialog({autoOpen:!1,width:window.innerWidth-80,height:window.innerHeight-80,modal:!0,title:(0,e.sprintf)((0,e.__)("Preview of table “%1$s” (ID %2$s)","tablepress"),l,tp.table.id),closeOnEscape:!0,buttons:[{text:(0,e.__)("OK","tablepress"),class:"button button-ok",click(){jQuery(this).wpdialog("close")}}]}),!tp.made_changes){const e=o("#table-preview-iframe");return e.src=t.target.href,e.removeAttribute("srcdoc"),void tp.callbacks.table_preview.$dialog.wpdialog("open")}tp.helpers.visibility.update();const n={action:"tablepress_preview_table",_ajax_nonce:tp.nonces.preview_table,tablepress:{id:tp.table.id,new_id:tp.table.new_id,name:o("#table-name").value,description:o("#table-description").value,data:JSON.stringify(tp.editor.options.data),options:JSON.stringify(tp.table.options),visibility:JSON.stringify(tp.table.visibility),number:{rows:tp.editor.options.data.length,columns:tp.editor.options.columns.length}}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-table-preview" class="spinner-table-preview spinner is-active" title="${(0,e.__)("The Table Preview is being loaded …","tablepress")}"/>`),o(".button-preview").forEach((e=>e.classList.add("disabled"))),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(n)}).then((e=>{if(!e.ok)throw new Error(`There was a problem with the server, HTTP response code ${e.status} (${e.statusText}).`);return e.json()})).then((e=>{if(null==e||"-1"===e||void 0===e.success)throw new Error("The JSON data returned from the server is unclear or incomplete.");if(!0!==e.success)throw new Error("The preview could not be loaded.");tp.callbacks.table_preview.success(e)})).catch((e=>tp.callbacks.table_preview.error(e.message))).finally((()=>{o("#spinner-table-preview").remove(),o(".button-preview").forEach((e=>e.classList.remove("disabled"))),document.body.classList.remove("wait")}))},tp.callbacks.table_preview.success=function(e){const t=o("#table-preview-iframe");t.src="",t.srcdoc=`<!DOCTYPE html><html><head>${e.head_html}</head><body>${e.body_html}</body></html>`,tp.callbacks.table_preview.$dialog.wpdialog("open")},tp.callbacks.table_preview.error=function(t){t=(0,e.__)("Attention: Unfortunately, an error occurred.","tablepress")+" "+t;const s=`show-preview-${Date.now()}`;o("#spinner-table-preview").parentNode.insertAdjacentHTML("afterend",`<div id="${s}" class="ajax-alert notice notice-error"><p>${t}</p></div>`);const l=o(`#${s}`);l.offsetWidth,l.style.opacity=0,l.addEventListener("transitionend",(()=>l.remove()))},tp.callbacks.save_changes={},tp.callbacks.save_changes.process=function(t){if(!tp.helpers.options.validate_fields())return;tp.helpers.visibility.update();const l={action:"tablepress_save_table",_ajax_nonce:tp.nonces.edit_table,tablepress:{id:tp.table.id,new_id:tp.table.new_id,name:o("#table-name").value,description:o("#table-description").value,data:JSON.stringify(tp.editor.options.data),options:JSON.stringify(tp.table.options),visibility:JSON.stringify(tp.table.visibility),number:{rows:tp.editor.options.data.length,columns:tp.editor.options.columns.length}}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-save-changes" class="spinner-save-changes spinner is-active" title="${(0,e.__)("Changes are being saved …","tablepress")}"/>`),o(".button-save-changes").forEach((e=>e.disabled=!0)),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(l)}).then((e=>{if(!e.ok)throw new Error(`There was a problem with the server, HTTP response code ${e.status} (${e.statusText}).`);return e.json()})).then((t=>{if(null==t||"-1"===t||void 0===t.success)throw new Error("The JSON data returned from the server is unclear or incomplete.");if(!0!==t.success){const s=(0,e.__)("These errors were encountered:","tablepress"),o=t.error_details?`</p><p>${s}</p><pre>${t.error_details}</pre><p>`:"";throw new Error(`The table could not be saved to the database properly.${o}`)}tp.callbacks.save_changes.success(t)})).catch((e=>tp.callbacks.save_changes.error(e.message))).finally((()=>{o("#spinner-save-changes").remove(),o(".button-save-changes").forEach((e=>e.disabled=!1)),document.body.classList.remove("wait")}))},tp.callbacks.save_changes.success=function(t){tp.table.id!==t.table_id&&window?.history?.pushState&&window.history.pushState("","",window.location.href.replace(/table_id=[0-9a-zA-Z-_]+/gi,`table_id=${t.table_id}`)),tp.table.id=t.table_id,tp.table.new_id=t.table_id,o("#table-id").value=t.table_id;const s=o("#table-information-shortcode");s&&(s.value=`[${tp.table.shortcode} id=${t.table_id} /]`),tp.nonces.edit_table=t.new_edit_nonce,tp.nonces.preview_table=t.new_preview_nonce,tp.nonces.copy_table=t.new_copy_nonce,tp.nonces.delete_table=t.new_delete_nonce,["preview","copy","delete"].forEach((e=>{o(`.button-${e}`).forEach((s=>{s.href=s.href.replace(/item=[a-zA-Z0-9_-]+/g,`item=${t.table_id}`).replace(/&_wpnonce=[a-z0-9]+/gi,`&_wpnonce=${t[`new_${e}_nonce`]}`)}))})),o(".button-export").forEach((e=>{e.href=e.href.replace(/table_id=[a-zA-Z0-9_-]+/g,`table_id=${t.table_id}`)})),o("#last-modified").textContent=t.last_modified,o("#last-editor").textContent=t.last_editor,tp.helpers.unsaved_changes.unset();const l={};if(l.success_save=(0,e.__)("The table was saved successfully.","tablepress"),l.success_save_success_id_change=l.success_save+" "+(0,e.__)("The table ID was changed.","tablepress"),l.success_save_error_id_change=l.success_save+" "+(0,e.__)("The table ID could not be changed, probably because the new ID is already in use!","tablepress"),"success_save_error_id_change"===t.message&&t.error_details){const s=(0,e.__)("These errors were encountered:","tablepress");l.success_save_error_id_change+=`</p><p>${s}</p><pre>${t.error_details}</pre><p>`}const n=t.message.includes("error")?"error":"success";tp.callbacks.save_changes.after_saving_notice(n,l[t.message])},tp.callbacks.save_changes.error=function(t){t=(0,e.__)("Attention: Unfortunately, an error occurred.","tablepress")+" "+t,tp.callbacks.save_changes.after_saving_notice("error",t)},tp.callbacks.save_changes.after_saving_notice=function(e,t){const s=`save-changes-${Date.now()}`;o("#spinner-save-changes").parentNode.insertAdjacentHTML("afterend",`<div id="${s}" class="ajax-alert notice notice-${e}"><p>${t}</p></div>`);const l=o(`#${s}`);l.offsetWidth,l.style.opacity=0,l.addEventListener("transitionend",(()=>l.remove()))},tp.callbacks.screen_options={},tp.callbacks.screen_options.update=function(e){if(e.target)return"table_editor_line_clamp"===e.target.id?(tp.editor.el.style.setProperty("--table-editor-line-clamp",parseInt(e.target.value,10)),void tp.editor.updateCornerPosition()):"table_editor_column_width"===e.target.id?(tp.screen_options.table_editor_column_width=parseInt(e.target.value,10),tp.screen_options.table_editor_column_width=Math.max(tp.screen_options.table_editor_column_width,30),tp.screen_options.table_editor_column_width=Math.min(tp.screen_options.table_editor_column_width,9999),tp.editor.colgroup.forEach((e=>e.setAttribute("width",tp.screen_options.table_editor_column_width))),void tp.editor.updateCornerPosition()):void 0},tp.callbacks.screen_options.set_was_changed=function(e){e.target&&(e.target.was_changed=!0)},tp.callbacks.screen_options.save=function(t){if(!t.target)return;if(!t.target.was_changed)return;t.target.was_changed=!1;const l={action:"tablepress_save_screen_options",_ajax_nonce:tp.nonces.screen_options,tablepress:{[t.target.id]:parseInt(t.target.value,10)}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-save-changes" class="spinner-save-changes spinner is-active" title="${(0,e.__)("Changes are being saved …","tablepress")}"/>`),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(l)}).finally((()=>{o("#spinner-save-changes").remove(),document.body.classList.remove("wait")}))},tp.callbacks.table_id=tp.callbacks.table_id||{},tp.callbacks.table_id.sanitize=function(){this.value=this.value.replace(/[^0-9a-zA-Z-_]/g,"")},tp.callbacks.table_id.change=function(){if(""===this.value||"0"===this.value)return window.alert((0,e.__)("This table ID is invalid. Please enter a different table ID.","tablepress")),this.value=tp.table.new_id,this.focus(),void this.select();if(!window.confirm((0,e.__)("Do you really want to change the Table ID? All blocks and Shortcodes for this table in your posts and pages will have to be adjusted!","tablepress")))return void(this.value=tp.table.new_id);tp.table.new_id=this.value;const t=o("#table-information-shortcode");t&&(t.value=`[${tp.table.shortcode} id=${tp.table.new_id} /]`,t.focus(),t.select()),tp.helpers.unsaved_changes.set()},tp.callbacks.insert_duplicate=function(e,t,s="before"){const o="rows"===t,l=o?tp.editor.insertRow:tp.editor.insertColumn,n=o?tp.editor.getRowData:tp.editor.getColumnData,a="duplicate"===e;tp.editor.options[o?"oninsertrow":"oninsertcolumn"]=tp.callbacks.editor.oninsertroc.bind(null,t,e),tp.helpers.selection[t].forEach((function(e,t){const o=e+t,i=a?n(o):1;l(i,o,"before"===s)})),tp.helpers.unsaved_changes.set();const i=tp.helpers.selection[t].length;i>1&&tp.editor.updateSelectionFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],o?tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]:tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]+i,o?tp.helpers.selection.rows[tp.helpers.selection.rows.length-1]+i:tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.callbacks.remove=function(e){const t="rows"===e,s=t?tp.editor.options.columns.length:tp.editor.options.data.length,o=t?tp.editor.options.data.length-1:tp.editor.options.columns.length-1;if(tp.editor.options.meta&&tp.helpers.selection[e].forEach((function(e){for(let o=0;o<s;o++){const s=t?[o,e]:[e,o];delete tp.editor.options.meta[jspreadsheet.getColumnNameFromId(s)]}})),(t?tp.editor.deleteRow:tp.editor.deleteColumn)(tp.helpers.selection[e][0],tp.helpers.selection[e].length),tp.helpers.unsaved_changes.set(),o===tp.helpers.selection[e][tp.helpers.selection[e].length-1]){const e=t?tp.helpers.selection.columns[0]:tp.helpers.selection.columns[0]-1,s=t?tp.helpers.selection.rows[0]-1:tp.helpers.selection.rows[0];tp.editor.updateSelectionFromCoords(e,s,e,s)}},tp.callbacks.append=function(e,t){const s="rows"===e,o=s?tp.editor.insertRow:tp.editor.insertColumn;tp.editor.options[s?"oninsertrow":"oninsertcolumn"]=tp.callbacks.editor.oninsertroc.bind(null,e,"append"),o(t),tp.helpers.unsaved_changes.set()},tp.callbacks.move=function(e,t){const s="rows"===t;let o=tp.helpers.selection[t],l=-1;if("down"===e||"right"===e)o=o.slice().reverse(),l=1;else if("top"===e||"first"===e)l=-o[0];else if("bottom"===e||"last"===e){o=o.slice().reverse();const e="rows"===t?tp.editor.options.data.length-1:tp.editor.options.columns.length-1;l=e-o[0]}if(0===l)return;const n=s?tp.editor.moveRow:tp.editor.moveColumn;o.forEach((e=>n(e,e+l))),tp.helpers.unsaved_changes.set(),tp.editor.updateSelectionFromCoords(s?tp.helpers.selection.columns[0]:tp.helpers.selection.columns[0]+l,s?tp.helpers.selection.rows[0]+l:tp.helpers.selection.rows[0],s?tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]:tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]+l,s?tp.helpers.selection.rows[tp.helpers.selection.rows.length-1]+l:tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.callbacks.sort=function(e){tp.editor.orderBy(tp.helpers.selection.columns[0],"desc"===e)},tp.callbacks.hide_unhide=function(e,t){const s="rows"===t,o=s?"row_hidden":"column_hidden",l=s?tp.editor.options.columns.length:tp.editor.options.data.length,n="hide"===e,a={};tp.helpers.selection[t].forEach((function(e){for(let t=0;t<l;t++){const l=s?[t,e]:[e,t],i=jspreadsheet.getColumnNameFromId(l);a[i]={},a[i][o]=n}})),tp.editor.setMeta(a),tp.helpers.unsaved_changes.set(),tp.editor.updateTable()},tp.callbacks.merge_cells=function(){const e=tp.helpers.selection.columns[0],t=tp.helpers.selection.rows[0],s=tp.helpers.selection.columns.length,o=tp.helpers.selection.rows.length;for(let s=1;s<o;s++)tp.editor.setValueFromCoords(e,t+s,"#rowspan#");for(let o=1;o<s;o++)tp.editor.setValueFromCoords(e+o,t,"#colspan#");for(let l=1;l<o;l++)for(let o=1;o<s;o++)tp.editor.setValueFromCoords(e+o,t+l,"#span#");tp.helpers.unsaved_changes.set()},tp.callbacks.keyboard_shortcuts=function(e){let t="",s="",l="";if((e.ctrlKey||e.metaKey)&&(80===e.keyCode?t="preview":83===e.keyCode?t="save-changes":76===e.keyCode?t="insert_link":73===e.keyCode?t="insert_image":69===e.keyCode?t="advanced_editor":e.shiftKey&&e.altKey&&38===e.keyCode?(t="move",s="top",l="rows"):e.shiftKey&&e.altKey&&40===e.keyCode?(t="move",s="bottom",l="rows"):e.shiftKey&&e.altKey&&37===e.keyCode?(t="move",s="first",l="columns"):e.shiftKey&&e.altKey&&39===e.keyCode?(t="move",s="last",l="columns"):e.shiftKey&&38===e.keyCode?(t="move",s="up",l="rows"):e.shiftKey&&40===e.keyCode?(t="move",s="down",l="rows"):e.shiftKey&&37===e.keyCode?(t="move",s="left",l="columns"):e.shiftKey&&39===e.keyCode&&(t="move",s="right",l="columns")),"save-changes"===t||"preview"===t)document.activeElement.blur(),document.querySelector(`#tablepress_edit-buttons-2-submit .button-${t}`).click(),e.preventDefault();else if("insert_link"===t||"insert_image"===t||"advanced_editor"===t){if(o("#table-editor").contains(document.activeElement)){const e="TEXTAREA"===document.activeElement.tagName?document.activeElement:null;tp.callbacks[t].open_dialog(e)}e.preventDefault()}else"move"===t&&(o("#table-editor").contains(document.activeElement)&&"TEXTAREA"!==document.activeElement.tagName&&tp.helpers.move_allowed(l,s)&&tp.callbacks.move(s,l),e.stopImmediatePropagation())},tp.editor=jspreadsheet(o("#table-editor"),{data:tp.table.data,meta:tp.helpers.visibility.load(),wordWrap:!0,rowDrag:!0,rowResize:!0,columnSorting:!0,columnDrag:!0,columnResize:!0,defaultColWidth:tp.screen_options.table_editor_column_width,defaultColAlign:"left",parseFormulas:!1,allowExport:!1,allowComments:!1,allowManualInsertRow:!1,allowManualInsertColumn:!1,about:!1,secureFormulas:!1,detachForUpdates:!0,onselection:tp.callbacks.editor.onselection,updateTable:tp.callbacks.editor.onupdatetable,contextMenu:t=>{const s=tp.editor.options.data.length,o=tp.editor.options.columns.length,l=tp.helpers.selection.rows.length,n=tp.helpers.selection.columns.length,a=window?.navigator?.platform?.includes("Mac"),i=a?(0,e._x)("⌘","keyboard shortcut modifier key on a Mac keyboard","tablepress"):(0,e._x)("Ctrl+","keyboard shortcut modifier key on a non-Mac keyboard","tablepress"),r=a?(0,e._x)("⌥","keyboard shortcut option key on a Mac keyboard","tablepress"):(0,e._x)("Alt+","keyboard shortcut Alt key on a non-Mac keyboard","tablepress"),c={text:""};return tp.helpers.visibility.update(),[{title:(0,e.__)("Undo","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sZ","keyboard shortcut for Undo","tablepress"),i),onclick:t.undo,disabled:-1===t.historyIndex},{title:(0,e.__)("Redo","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sY","keyboard shortcut for Redo","tablepress"),i),onclick:t.redo,disabled:t.historyIndex===t.history.length-1},{type:"divisor"},{title:(0,e.__)("Cut","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sX","keyboard shortcut for Cut","tablepress"),i),onclick(){if("TEXTAREA"===document.activeElement.tagName&&document.activeElement.selectionStart!==document.activeElement.selectionEnd){document.execCommand("copy");const e=document.activeElement.selectionStart;document.activeElement.value=document.activeElement.value.slice(0,document.activeElement.selectionStart)+document.activeElement.value.slice(document.activeElement.selectionEnd),document.activeElement.selectionEnd=e}else t.copy(!0),t.setValue(t.highlighted,"")}},{title:(0,e.__)("Copy","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sC","keyboard shortcut for Copy","tablepress"),i),onclick(){"TEXTAREA"===document.activeElement.tagName&&document.activeElement.selectionStart!==document.activeElement.selectionEnd?document.execCommand("copy"):t.copy(!0)}},{title:(0,e.__)("Paste","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sV","keyboard shortcut for Paste","tablepress"),i),onclick(){"TEXTAREA"===document.activeElement.tagName?window.navigator.clipboard.readText().then((e=>{if(e){const t=document.activeElement.selectionStart+e.length;document.activeElement.value=document.activeElement.value.slice(0,document.activeElement.selectionStart)+e+document.activeElement.value.slice(document.activeElement.selectionEnd),document.activeElement.selectionEnd=t}})):t.selectedCell&&window.navigator.clipboard.readText().then((e=>{e&&t.paste(t.selectedCell[0],t.selectedCell[1],e)}))},disabled:!window?.navigator?.clipboard?.readText,tooltip:window?.navigator?.clipboard?.readText?"":(0,e.__)("Your browser does not allow pasting via the context menu. Use the keyboard shortcut instead.","tablepress")},{type:"divisor"},{title:(0,e.__)("Insert Link","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sL","keyboard shortcut for Insert Link","tablepress"),i),onclick:tp.callbacks.insert_link.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{title:(0,e.__)("Insert Image","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sI","keyboard shortcut for Insert Image","tablepress"),i),onclick:tp.callbacks.insert_image.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{title:(0,e.__)("Advanced Editor","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sE","keyboard shortcut for Advanced Editor","tablepress"),i),onclick:tp.callbacks.advanced_editor.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{type:"divisor"},{title:(0,e.__)("Duplicate …","tablepress"),submenu:[{title:(0,e._n)("Duplicate row","Duplicate rows",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"duplicate","rows")},{title:(0,e._n)("Duplicate column","Duplicate columns",n,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"duplicate","columns")}]},{title:(0,e.__)("Insert …","tablepress"),submenu:[{title:(0,e._n)("Insert row above","Insert rows above",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","rows","before")},{title:(0,e._n)("Insert row below","Insert rows below",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","rows","after")},{title:(0,e._n)("Insert column on the left","Insert columns on the left",n,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","columns","before")},{title:(0,e._n)("Insert column on the right","Insert columns on the right",n,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","columns","after")}]},{title:(0,e.__)("Append …","tablepress"),submenu:[{title:(0,e.__)("Append row","tablepress"),onclick:tp.callbacks.append.bind(null,"rows",1)},{title:(0,e.__)("Append column","tablepress"),onclick:tp.callbacks.append.bind(null,"columns",1)}]},{title:(0,e.__)("Delete …","tablepress"),submenu:[{title:(0,e._n)("Delete row","Delete rows",l,"tablepress"),onclick:tp.callbacks.remove.bind(null,"rows"),disabled:s===l,tooltip:s===l?(0,e.__)("This option is disabled.","tablepress")+" "+(0,e.__)("You can not delete all table rows!","tablepress"):""},{title:(0,e._n)("Delete column","Delete columns",n,"tablepress"),onclick:tp.callbacks.remove.bind(null,"columns"),disabled:o===n,tooltip:o===n?(0,e.__)("This option is disabled.","tablepress")+" "+(0,e.__)("You can not delete all table columns!","tablepress"):""}]},{type:"divisor"},{title:(0,e.__)("Move …","tablepress"),submenu:[{title:(0,e._n)("Move row up","Move rows up",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧↑","keyboard shortcut for Move up","tablepress"),i),onclick:tp.callbacks.move.bind(null,"up","rows"),disabled:!tp.helpers.move_allowed("rows","up")},{title:(0,e._n)("Move row down","Move rows down",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧↓","keyboard shortcut for Move down","tablepress"),i),onclick:tp.callbacks.move.bind(null,"down","rows"),disabled:!tp.helpers.move_allowed("rows","down")},{title:(0,e._n)("Move column left","Move columns left",n,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧←","keyboard shortcut for Move left","tablepress"),i),onclick:tp.callbacks.move.bind(null,"left","columns"),disabled:!tp.helpers.move_allowed("columns","left")},{title:(0,e._n)("Move column right","Move columns right",n,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧→","keyboard shortcut for Move right","tablepress"),i),onclick:tp.callbacks.move.bind(null,"right","columns"),disabled:!tp.helpers.move_allowed("columns","right")},{type:"divisor"},{title:(0,e._n)("Move row to the top","Move rows to the top",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧↑","keyboard shortcut for Move to the top","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"top","rows"),disabled:!tp.helpers.move_allowed("rows","top")},{title:(0,e._n)("Move row to the bottom","Move rows to the bottom",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧↓","keyboard shortcut for Move to the bottom","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"bottom","rows"),disabled:!tp.helpers.move_allowed("rows","bottom")},{title:(0,e._n)("Move column to first","Move columns to first",n,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧←","keyboard shortcut for Move to first","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"first","columns"),disabled:!tp.helpers.move_allowed("columns","first")},{title:(0,e._n)("Move column to last","Move columns to last",n,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧→","keyboard shortcut for Move to last","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"last","columns"),disabled:!tp.helpers.move_allowed("columns","last")}]},{title:(0,e.__)("Sort by column …","tablepress"),submenu:[{title:(0,e.__)("Sort by column ascending","tablepress"),onclick:tp.callbacks.sort.bind(null,"asc"),disabled:1!==n,tooltip:1!==n?(0,e.__)("This option is disabled because more than one column was selected.","tablepress"):""},{title:(0,e.__)("Sort by column descending","tablepress"),onclick:tp.callbacks.sort.bind(null,"desc"),disabled:1!==n,tooltip:1!==n?(0,e.__)("This option is disabled because more than one column was selected.","tablepress"):""}]},{type:"divisor"},{title:(0,e.__)("Hide/Show …","tablepress"),submenu:[{title:(0,e._n)("Hide row","Hide rows",l,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"hide","rows"),disabled:!tp.helpers.visibility.selection_contains("rows",1),tooltip:tp.helpers.visibility.selection_contains("rows",1)?"":(0,e.__)("This option is disabled because no visible rows were selected.","tablepress")},{title:(0,e._n)("Hide column","Hide columns",n,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"hide","columns"),disabled:!tp.helpers.visibility.selection_contains("columns",1),tooltip:tp.helpers.visibility.selection_contains("columns",1)?"":(0,e.__)("This option is disabled because no visible columns were selected.","tablepress")},{title:(0,e._n)("Show row","Show rows",l,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"unhide","rows"),disabled:!tp.helpers.visibility.selection_contains("rows",0),tooltip:tp.helpers.visibility.selection_contains("rows",0)?"":(0,e.__)("This option is disabled because no hidden rows were selected.","tablepress")},{title:(0,e._n)("Show column","Show columns",n,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"unhide","columns"),disabled:!tp.helpers.visibility.selection_contains("columns",0),tooltip:tp.helpers.visibility.selection_contains("columns",0)?"":(0,e.__)("This option is disabled because no hidden columns were selected.","tablepress")}]},{type:"divisor"},{title:(0,e.__)("Combine/Merge cells","tablepress"),onclick:tp.callbacks.merge_cells,disabled:1===l&&1===n||!tp.helpers.cell_merge_allowed("no-alert"),tooltip:1===l&&1===n||!tp.helpers.cell_merge_allowed("no-alert",c)?(0,e.__)("This option is disabled.","tablepress")+" "+c.text:""}]},sorting:tp.helpers.editor.sorting,onmoverow:tp.callbacks.editor.onmove,onmovecolumn:tp.callbacks.editor.onmove,onblur:tp.helpers.editor.reselect,onload:tp.helpers.editor.reselect,onchange:tp.helpers.unsaved_changes.set,onsort:tp.callbacks.editor.onsort}),tp.helpers.options.load(),o("#tablepress-page").addEventListener("click",(e=>{e.target&&(e.target.matches(".button-preview")?tp.callbacks.table_preview.process(e):e.target.matches(".button-save-changes")?tp.callbacks.save_changes.process(e):e.target.matches(".button-show-help-box")&&tp.callbacks.help_box.open_dialog(e))})),o("#tablepress-manipulation-controls").addEventListener("click",(t=>{if(t.target)if(t.target.matches(".button-append")){const s=t.target.dataset.type,l=o(`#${s}-append-number`),n=parseInt(l.value,10);if(isNaN(n)||n<1||n>99999){const s="rows"===t.target.dataset.type?(0,e.__)("The value for the number of rows is invalid!","tablepress"):(0,e.__)("The value for the number of columns is invalid!","tablepress");return window.alert(s),l.focus(),void l.select()}tp.callbacks.append(s,n)}else if("button-insert-link"!==t.target.id)if("button-insert-image"!==t.target.id)if("button-advanced-editor"!==t.target.id)if(t.target.matches(".button-insert-duplicate"))tp.callbacks.insert_duplicate(t.target.dataset.action,t.target.dataset.type);else{if(t.target.matches(".button-move"))return tp.helpers.move_allowed(t.target.dataset.type,t.target.dataset.direction)?void tp.callbacks.move(t.target.dataset.direction,t.target.dataset.type):void window.alert((0,e.__)("You can not do this move, because you reached the border of the table.","tablepress"));if(t.target.matches(".button-remove")){const s="rows"===t.target.dataset.type;if((s?tp.editor.options.data.length:tp.editor.options.columns.length)===tp.helpers.selection[t.target.dataset.type].length){const t=s?(0,e.__)("You can not delete all table rows!","tablepress"):(0,e.__)("You can not delete all table columns!","tablepress");return void window.alert(t)}tp.callbacks.remove(t.target.dataset.type)}else t.target.matches(".button-merge-unmerge")?tp.helpers.cell_merge_allowed("alert")&&tp.callbacks.merge_cells():t.target.matches(".button-hide-unhide")&&tp.callbacks.hide_unhide(t.target.dataset.action,t.target.dataset.type)}else tp.callbacks.advanced_editor.open_dialog();else tp.callbacks.insert_image.open_dialog();else tp.callbacks.insert_link.open_dialog()}));const l=o("#table-id");l.addEventListener("input",tp.callbacks.table_id.sanitize),l.addEventListener("change",tp.callbacks.table_id.change);const n=o("#table-information-shortcode");n&&n.addEventListener("focus",(function(){this.select()})),jQuery("#textarea-insert-helper").on("change",tp.helpers.editor.insert_from_helper_textarea),["#table-name","#table-description"].forEach((e=>o(e).addEventListener("change",tp.helpers.unsaved_changes.set))),(0,t.applyFilters)("tablepress.optionsMetaBoxes",["#tablepress_edit-table-options","#tablepress_edit-datatables-features"]).forEach((e=>o(e).addEventListener("change",tp.helpers.options.change))),document.querySelectorAll("#tablepress-body .button-module-help").forEach((e=>e.closest(".postbox").querySelector(".handle-actions").prepend(e)));const a=o("#tablepress-screen-options");a.addEventListener("input",tp.callbacks.screen_options.update),a.addEventListener("change",tp.callbacks.screen_options.set_was_changed),a.addEventListener("focusout",tp.callbacks.screen_options.save),window.addEventListener("keydown",tp.callbacks.keyboard_shortcuts,!0);const i=window?.navigator?.platform?.includes("Mac")?(0,e._x)("⌘","keyboard shortcut modifier key on a Mac keyboard","tablepress"):(0,e._x)("Ctrl+","keyboard shortcut modifier key on a non-Mac keyboard","tablepress");document.querySelectorAll(".button[data-shortcut]").forEach((t=>{const s=(0,e.sprintf)(t.dataset.shortcut,i);t.title=(0,e.sprintf)((0,e.__)("Keyboard Shortcut: %s","tablepress"),s)})),jQuery((function(){jQuery("#wp-link").on("focus","input",(function(e){e.stopPropagation()})),jQuery("body").on("focus",".media-modal .media-frame-content input, .media-modal .media-frame-content textarea",(function(e){e.stopPropagation()}))}))}();
\ No newline at end of file
diff --git a/admin/js/edit.js b/admin/js/edit.js
index 4e5402e..2c4f04a 100644
--- a/admin/js/edit.js
+++ b/admin/js/edit.js
@@ -763,11 +763,11 @@ tp.callbacks.table_preview.process = function ( event ) {
 		},
 	};
 
 	// Add spinner, disable "Preview" buttons, and change cursor.
 	event.target.parentNode.insertAdjacentHTML( 'beforeend', `<span id="spinner-table-preview" class="spinner-table-preview spinner is-active" title="${ __( 'The Table Preview is being loaded …', 'tablepress' ) }"/>` );
-	$( '.button-show-preview' ).forEach( ( button ) => button.classList.add( 'disabled' ) );
+	$( '.button-preview' ).forEach( ( button ) => button.classList.add( 'disabled' ) );
 	document.body.classList.add( 'wait' );
 
 	// Load the table preview data from the server via an AJAX request.
 	fetch( ajaxurl, {
 		method: 'POST',
@@ -798,11 +798,11 @@ tp.callbacks.table_preview.process = function ( event ) {
 	} )
 	// Handle errors.
 	.catch( ( error ) => tp.callbacks.table_preview.error( error.message ) )
 	.finally( () => {
 		$( '#spinner-table-preview' ).remove();
-		$( '.button-show-preview' ).forEach( ( button ) => button.classList.remove( 'disabled' ) );
+		$( '.button-preview' ).forEach( ( button ) => button.classList.remove( 'disabled' ) );
 		document.body.classList.remove( 'wait' );
 	} );
 };
 
 /**
@@ -936,16 +936,26 @@ tp.callbacks.save_changes.success = function ( data ) {
 	}
 
 	// Update the nonces.
 	tp.nonces.edit_table = data.new_edit_nonce;
 	tp.nonces.preview_table = data.new_preview_nonce;
+	tp.nonces.copy_table = data.new_copy_nonce;
+	tp.nonces.delete_table = data.new_delete_nonce;
+
+	// Update URLs in Preview, Copy, and Delete links/buttons.
+	[ 'preview', 'copy', 'delete' ].forEach( ( action ) => {
+		$( `.button-${ action }` ).forEach( ( button ) => {
+			button.href = button.href
+				.replace( /item=[a-zA-Z0-9_-]+/g, `item=${ data.table_id }` ) // Updates both the "item" and the "return_item" parameters.
+				.replace( /&_wpnonce=[a-z0-9]+/ig, `&_wpnonce=${ data[ `new_${ action }_nonce` ] }` );
+		} );
+	} );
 
-	// Update URLs in Preview links.
-	$( '.button-show-preview' ).forEach( ( button ) => {
+	// Update URL in Export links/buttons.
+	$( '.button-export' ).forEach( ( button ) => {
 		button.href = button.href
-			.replace( /item=[a-zA-Z0-9_-]+/g, `item=${ data.table_id }` )
-			.replace( /&_wpnonce=[a-z0-9]+/ig, `&_wpnonce=${ data.new_preview_nonce }` );
+			.replace( /table_id=[a-zA-Z0-9_-]+/g, `table_id=${ data.table_id }` );
 	} );
 
 	// Update last-modified date and user nickname.
 	$( '#last-modified' ).textContent = data.last_modified;
 	$( '#last-editor' ).textContent = data.last_editor;
@@ -1307,11 +1317,11 @@ tp.callbacks.keyboard_shortcuts = function ( event ) {
 	let move_type = '';
 
 	if ( event.ctrlKey || event.metaKey ) {
 		if ( 80 === event.keyCode ) {
 			// Preview: Ctrl/Cmd + P.
-			action = 'show-preview';
+			action = 'preview';
 		} else if ( 83 === event.keyCode ) {
 			// Save Changes: Ctrl/Cmd + S.
 			action = 'save-changes';
 		} else if ( 76 === event.keyCode ) {
 			// Insert Link: Ctrl/Cmd + L.
@@ -1363,11 +1373,11 @@ tp.callbacks.keyboard_shortcuts = function ( event ) {
 			move_direction = 'right';
 			move_type = 'columns';
 		}
 	}
 
-	if ( 'save-changes' === action || 'show-preview' === action ) {
+	if ( 'save-changes' === action || 'preview' === action ) {
 		// Blur the focussed element to make sure that all change events were triggered.
 		document.activeElement.blur(); // eslint-disable-line @wordpress/no-global-active-element
 
 		/*
 		 * Emulate a click on the button corresponding to the action.
@@ -1444,11 +1454,11 @@ tp.helpers.options.load();
 $( '#tablepress-page' ).addEventListener( 'click', ( event ) => {
 	if ( ! event.target ) {
 		return;
 	}
 
-	if ( event.target.matches( '.button-show-preview' ) ) {
+	if ( event.target.matches( '.button-preview' ) ) {
 		tp.callbacks.table_preview.process( event );
 		return;
 	}
 
 	if ( event.target.matches( '.button-save-changes' ) ) {
diff --git a/blocks/table/block.json b/blocks/table/block.json
index babcfd8..2188f97 100644
--- a/blocks/table/block.json
+++ b/blocks/table/block.json
@@ -1,10 +1,10 @@
 {
 	"$schema": "https://schemas.wp.org/trunk/block.json",
 	"apiVersion": 3,
 	"name": "tablepress/table",
-	"version": "2.2.4",
+	"version": "2.2.5",
 	"title": "TablePress table",
 	"category": "media",
 	"icon": "list-view",
 	"description": "Embed a TablePress table.",
 	"keywords": [ "table" ],
diff --git a/classes/class-import-phpspreadsheet.php b/classes/class-import-phpspreadsheet.php
index 5c26885..d15b526 100644
--- a/classes/class-import-phpspreadsheet.php
+++ b/classes/class-import-phpspreadsheet.php
@@ -75,14 +75,16 @@ class TablePress_Import_PHPSpreadsheet extends TablePress_Import_Base {
 	 *
 	 * @param string $data Data to import.
 	 * @return array<string, mixed>|false Table array on success, false if the file is not a JSON file.
 	 */
 	protected function _maybe_import_json( string $data ) /* : array|false */ {
-		// If the first non-whitespace character is not a { or [, the file is not a supported JSON file.
-		$data = ltrim( $data );
+		$data = trim( $data );
+
+		// If the file does not begin / end with [ / ] or { / }, it's not a supported JSON file.
 		$first_character = $data[0];
-		if ( '{' !== $first_character && '[' !== $first_character ) {
+		$last_character = $data[-1];
+		if ( ! ( '[' === $first_character && ']' === $last_character ) && ! ( '{' === $first_character && '}' === $last_character ) ) {
 			return false;
 		}
 
 		$json_table = json_decode( $data, true );
 
@@ -244,13 +246,20 @@ class TablePress_Import_PHPSpreadsheet extends TablePress_Import_Base {
 						$cell_data = (string) $value;
 					}
 
 					// Apply data type formatting.
 					$style = $spreadsheet->getCellXfByIndex( $cell->getXfIndex() );
+
+					$format = $style->getNumberFormat()->getFormatCode() ?? \TablePress\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_GENERAL;
+
+					// Fix floating point precision issues with numbers in the "General" Excel .xlsx format.
+					if ( 'xlsx' === $detected_format && \TablePress\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_GENERAL === $format && is_numeric( $cell_data ) ) {
+						$cell_data = (string) (float) $cell_data; // Type-cast strings to float and back.
+					}
 					$cell_data = \TablePress\PhpOffice\PhpSpreadsheet\Style\NumberFormat::toFormattedString(
 						$cell_data,
-						$style->getNumberFormat() ? $style->getNumberFormat()->getFormatCode() : \TablePress\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_GENERAL, // @phpstan-ignore-line
+						$format,
 						array( $this, 'format_color' )
 					);
 
 					if ( strlen( $cell_data ) > 1 && '=' === $cell_data[0] ) {
 						if ( $style->getQuotePrefix() ) {
diff --git a/classes/class-import.php b/classes/class-import.php
index 9033a71..37cff2f 100644
--- a/classes/class-import.php
+++ b/classes/class-import.php
@@ -125,16 +125,20 @@ class TablePress_Import {
 
 				if ( empty( $host ) ) {
 					return new WP_Error( 'table_import_url_host_invalid', '', $this->import_config['url'] );
 				}
 
-				// Check the host of the Import URL against a blacklist of hosts, which should not be accessible, e.g. for security considerations.
-				$blocked_hosts = array(
-					'169.254.169.254', // AWS Meta-data API.
+				// Check the IP address of the host against a blocklist of hosts which should not be accessible, e.g. for security considerations.
+				$ip = gethostbyname( $host ); // If no IP address can be found, this will return the host name, which will then be checked against the blocklist.
+				$blocked_ips = array(
+					'169.254.169.254', // Meta-data API for various cloud providers.
+					'169.254.170.2', // AWS task metadata endpoint.
+					'192.0.0.192', // Oracle Cloud endpoint.
+					'100.100.100.200', // Alibaba Cloud endpoint.
 				);
-				if ( in_array( $host, $blocked_hosts, true ) ) {
-					return new WP_Error( 'table_import_url_host_blocked', '', $this->import_config['url'] );
+				if ( in_array( $ip, $blocked_ips, true ) ) {
+					return new WP_Error( 'table_import_url_host_blocked', '', array( 'url' => $this->import_config['url'], 'ip' => $ip ) );
 				}
 
 				/**
 				 * Load WP file functions to be sure that `download_url()` exists, in particular during Cron requests.
 				 */
@@ -393,11 +397,11 @@ class TablePress_Import {
 		// Use the legacy import class, if the requirements for PHPSpreadsheet are not fulfilled.
 		$phpspreadsheet_requirements_fulfilled = extension_loaded( 'mbstring' )
 			&& class_exists( 'ZipArchive', false )
 			&& class_exists( 'DOMDocument', false )
 			&& function_exists( 'simplexml_load_string' )
-			&& function_exists( 'libxml_disable_entity_loader' );
+			&& ( function_exists( 'libxml_disable_entity_loader' ) || PHP_VERSION_ID >= 80000 ); // This function is only needed for older versions of PHP.
 		if ( ! $phpspreadsheet_requirements_fulfilled ) {
 			return true;
 		}
 
 		// Use the legacy import class, if the PHPSpreadsheet files do not exist (e.g. because `composer install` was not run).
@@ -529,15 +533,21 @@ class TablePress_Import {
 			return new WP_Error( 'table_import_legacy_data_empty', '', $file['location'] );
 		}
 
 		// If no format could be determined from the file extension, try guessing from the file content.
 		if ( '' === $format ) {
+			$data = trim( $data );
 			$first_character = $data[0];
-			if ( '<' === $first_character ) {
+			$last_character = $data[-1];
+
+			if ( '<' === $first_character && '>' === $last_character ) {
 				$format = 'html';
-			} elseif ( '{' === $first_character || '[' === $first_character ) {
-				$format = 'json';
+			} elseif ( ( '[' === $first_character && ']' === $last_character ) || ( '{' === $first_character && '}' === $last_character ) ) {
+				$json_table = json_decode( $data, true );
+				if ( ! is_null( $json_table ) ) {
+					$format = 'json';
+				}
 			}
 		}
 
 		// Fall back to CSV if no file format could be determined.
 		if ( '' === $format ) {
diff --git a/classes/class-tablepress.php b/classes/class-tablepress.php
index c9f4f14..64c4655 100644
--- a/classes/class-tablepress.php
+++ b/classes/class-tablepress.php
@@ -25,21 +25,21 @@ abstract class TablePress {
 	 * Increases whenever a new plugin version is released.
 	 *
 	 * @since 1.0.0
 	 * @const string
 	 */
-	public const version = '2.2.4'; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
+	public const version = '2.2.5'; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
 
 	/**
 	 * TablePress internal plugin version ("options scheme" version).
 	 *
 	 * Increases whenever the scheme for the plugin options changes, or on a plugin update.
 	 *
 	 * @since 1.0.0
 	 * @const int
 	 */
-	public const db_version = 70; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
+	public const db_version = 73; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
 
 	/**
 	 * TablePress "table scheme" (data format structure) version.
 	 *
 	 * Increases whenever the scheme for a $table changes,
diff --git a/classes/class-view.php b/classes/class-view.php
index 9107a7c..e7075cc 100644
--- a/classes/class-view.php
+++ b/classes/class-view.php
@@ -409,11 +409,11 @@ abstract class TablePress_View {
 	 */
 	protected function print_nav_tab_menu(): void {
 		?>
 		<div id="tablepress-header" class="header">
 			<h1 class="name"><img src="<?php echo plugins_url( 'admin/img/tablepress-icon.png', TABLEPRESS__FILE__ ); ?>" class="tablepress-icon" alt="<?php esc_attr_e( 'TablePress plugin logo', 'tablepress' ); ?>" /><?php _e( 'TablePress', 'tablepress' ); ?></h1>
-			<?php if ( tb_tp_fs()->is_free_plan() ) : ?>
+			<?php if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) : ?>
 				<div class="buttons">
 					<a href="https://tablepress.org/premium/?utm_source=plugin&utm_medium=button&utm_content=upgrade-button" class="tablepress-button">
 						<span><?php _e( 'Upgrade to Premium', 'tablepress' ); ?></span>
 						<span class="dashicons dashicons-arrow-right-alt" />
 					</a>
diff --git a/controllers/controller-admin.php b/controllers/controller-admin.php
index c744ec8..e825151 100644
--- a/controllers/controller-admin.php
+++ b/controllers/controller-admin.php
@@ -408,11 +408,11 @@ JS;
 	public function add_plugin_row_meta( array $links, string $file ): array {
 		if ( TABLEPRESS_BASENAME === $file ) {
 			$links[] = '<a href="https://tablepress.org/faq/" title="' . esc_attr__( 'Frequently Asked Questions', 'tablepress' ) . '">' . __( 'FAQ', 'tablepress' ) . '</a>';
 			$links[] = '<a href="https://tablepress.org/documentation/">' . __( 'Documentation', 'tablepress' ) . '</a>';
 			$links[] = '<a href="https://tablepress.org/support/">' . __( 'Support', 'tablepress' ) . '</a>';
-			if ( tb_tp_fs()->is_free_plan() ) {
+			if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) {
 				$links[] = '<a href="https://tablepress.org/premium/?utm_source=plugin&utm_medium=textlink&utm_content=plugins-screen" title="' . esc_attr__( 'Check out the Premium version of TablePress!', 'tablepress' ) . '"><strong>' . __( 'Go Premium', 'tablepress' ) . '</strong></a>';
 			}
 		}
 		return $links;
 	}
@@ -788,11 +788,11 @@ JS;
 			TablePress::redirect( array( 'action' => 'add', 'message' => 'error_add', 'error_details' => 'The HTTP POST data is empty.' ) );
 		}
 
 		$add_table = wp_unslash( $_POST['table'] );
 
-		// Perform sanity checks of posted data.
+		// Perform confidence checks of posted data.
 		$name = ( isset( $add_table['name'] ) ) ? $add_table['name'] : '';
 		$description = ( isset( $add_table['description'] ) ) ? $add_table['description'] : '';
 		if ( ! isset( $add_table['rows'], $add_table['columns'] ) ) {
 			TablePress::redirect( array( 'action' => 'add', 'message' => 'error_add', 'error_details' => 'The HTTP POST data does not contain the table size.' ) );
 		}
diff --git a/controllers/controller-admin_ajax.php b/controllers/controller-admin_ajax.php
index 2bb8b39..124f2ef 100644
--- a/controllers/controller-admin_ajax.php
+++ b/controllers/controller-admin_ajax.php
@@ -172,10 +172,12 @@ class TablePress_Admin_AJAX_Controller extends TablePress_Controller {
 		);
 		if ( $success ) {
 			$response['table_id'] = $table['id']; // @phpstan-ignore-line
 			$response['new_edit_nonce'] = wp_create_nonce( TablePress::nonce( 'edit', $table['id'] ) ); // @phpstan-ignore-line
 			$response['new_preview_nonce'] = wp_create_nonce( TablePress::nonce( 'preview_table', $table['id'] ) ); // @phpstan-ignore-line
+			$response['new_copy_nonce'] = wp_create_nonce( TablePress::nonce( 'copy_table', $table['id'] ) ); // @phpstan-ignore-line
+			$response['new_delete_nonce'] = wp_create_nonce( TablePress::nonce( 'delete_table', $table['id'] ) ); // @phpstan-ignore-line
 			$response['last_modified'] = TablePress::format_datetime( $table['last_modified'] ); // @phpstan-ignore-line
 			$response['last_editor'] = TablePress::get_user_display_name( $table['options']['last_editor'] ); // @phpstan-ignore-line
 		}
 		if ( ! empty( $error_details ) ) {
 			$response['error_details'] = esc_html( $error_details );
diff --git a/controllers/controller-frontend.php b/controllers/controller-frontend.php
index 85d9534..6bbb17c 100644
--- a/controllers/controller-frontend.php
+++ b/controllers/controller-frontend.php
@@ -251,10 +251,12 @@ class TablePress_Frontend_Controller extends TablePress_Controller {
 		$datatables_language = array();
 		// Generate the specific JS commands, depending on chosen features on the "Edit" screen and the Shortcode parameters.
 		$commands = array();
 
 		foreach ( $this->shown_tables as $table_id => $table_store ) {
+			$table_id = (string) $table_id; // Ensure that the table ID is a string, as it comes from an array key where numeric strings are converted to integers.
+
 			if ( empty( $table_store['instances'] ) ) {
 				continue;
 			}
 
 			foreach ( $table_store['instances'] as $html_id => $js_options ) {
@@ -512,11 +514,11 @@ JS;
 		$shortcode_atts = apply_filters( 'tablepress_shortcode_table_shortcode_atts', $shortcode_atts );
 
 		// Check, if a table with the given ID exists.
 		$table_id = (string) preg_replace( '/[^a-zA-Z0-9_-]/', '', $shortcode_atts['id'] );
 		if ( ! TablePress::$model_table->table_exists( $table_id ) ) {
-			$message = "[table &#8220;{$table_id}&#8221; not found /]<br />\n";
+			$message = "&#91;table “{$table_id}” not found /&#93;<br />\n";
 			/**
 			 * Filters the "Table not found" message.
 			 *
 			 * @since 1.0.0
 			 *
@@ -528,11 +530,11 @@ JS;
 		}
 
 		// Load table, with table data, options, and visibility settings.
 		$table = TablePress::$model_table->load( $table_id, true, true );
 		if ( is_wp_error( $table ) ) {
-			$message = "[table &#8220;{$table_id}&#8221; could not be loaded /]<br />\n";
+			$message = "&#91;table “{$table_id}” could not be loaded /&#93;<br />\n";
 			/**
 			 * Filters the "Table could not be loaded" message.
 			 *
 			 * @since 1.0.0
 			 *
@@ -542,11 +544,11 @@ JS;
 			 */
 			$message = apply_filters( 'tablepress_table_load_error_message', $message, $table_id, $table );
 			return $message;
 		}
 		if ( isset( $table['is_corrupted'] ) && $table['is_corrupted'] ) {
-			$message = "<div>Attention: The internal data of table &#8220;{$table_id}&#8221; is corrupted!</div>";
+			$message = "<div>Attention: The internal data of table “{$table_id}” is corrupted!</div>";
 			/**
 			 * Filters the "Table data is corrupted" message.
 			 *
 			 * @since 1.0.0
 			 *
@@ -784,20 +786,20 @@ JS;
 		}
 
 		// Check, if a table with the given ID exists.
 		$table_id = preg_replace( '/[^a-zA-Z0-9_-]/', '', $shortcode_atts['id'] );
 		if ( ! TablePress::$model_table->table_exists( $table_id ) ) {
-			$message = "[table &#8220;{$table_id}&#8221; not found /]<br />\n";
+			$message = "&#91;table “{$table_id}” not found /&#93;<br />\n";
 			/** This filter is documented in controllers/controller-frontend.php */
 			$message = apply_filters( 'tablepress_table_not_found_message', $message, $table_id );
 			return $message;
 		}
 
 		// Load table, with table data, options, and visibility settings.
 		$table = TablePress::$model_table->load( $table_id, true, true );
 		if ( is_wp_error( $table ) ) {
-			$message = "[table &#8220;{$table_id}&#8221; could not be loaded /]<br />\n";
+			$message = "&#91;table “{$table_id}” could not be loaded /&#93;<br />\n";
 			/** This filter is documented in controllers/controller-frontend.php */
 			$message = apply_filters( 'tablepress_table_load_error_message', $message, $table_id, $table );
 			return $message;
 		}
 
@@ -858,11 +860,11 @@ JS;
 				break;
 			case 'number_columns':
 				$output = count( $table['data'][0] );
 				break;
 			default:
-				$output = "[table-info field &#8220;{$field}&#8221; not found in table &#8220;{$table_id}&#8221; /]<br />\n";
+				$output = "&#91;table-info field “{$field}” not found in table “{$table_id}” /&#93;<br />\n";
 				/**
 				 * Filters the "table info field not found" message.
 				 *
 				 * @since 1.0.0
 				 *
diff --git a/libraries/freemius/includes/class-freemius.php b/libraries/freemius/includes/class-freemius.php
index 4b5c18a..addb9e3 100644
--- a/libraries/freemius/includes/class-freemius.php
+++ b/libraries/freemius/includes/class-freemius.php
@@ -1355,12 +1355,11 @@
 				);
 			}
 		}
 
 		function _run_garbage_collector() {
-			// @todo - Remove this check once the garbage collector is ready to be out of beta.
-			if ( true !== fs_get_optional_constant( 'WP_FS__ENABLE_GARBAGE_COLLECTOR', false ) ) {
+			if ( true !== fs_get_optional_constant( 'WP_FS__ENABLE_GARBAGE_COLLECTOR', true ) ) {
 				return;
 			}
 
 			if ( ! $this->is_user_in_admin() ) {
 				return;
diff --git a/libraries/freemius/includes/class-fs-garbage-collector.php b/libraries/freemius/includes/class-fs-garbage-collector.php
index 145774d..127a794 100644
--- a/libraries/freemius/includes/class-fs-garbage-collector.php
+++ b/libraries/freemius/includes/class-fs-garbage-collector.php
@@ -279,11 +279,11 @@
 			$products_user_id_license_ids_map = $this->_accounts->get_option( 'user_id_license_ids_map', array() );
 
 			$has_updated_option = false;
 
 			foreach ( $users as $user_id => $user ) {
-				if ( ! isset( $user_has_install[ $user_id ] ) ) {
+				if ( ! isset( $user_has_install_map[ $user_id ] ) ) {
 					unset( $users[ $user_id ] );
 
 					foreach( $products_user_id_license_ids_map as $product_id => $user_id_license_ids_map ) {
 						unset( $user_id_license_ids_map[ $user_id ] );
 
diff --git a/libraries/freemius/start.php b/libraries/freemius/start.php
index 03c22a4..b7599c0 100644
--- a/libraries/freemius/start.php
+++ b/libraries/freemius/start.php
@@ -13,11 +13,11 @@
 	/**
 	 * Freemius SDK Version.
 	 *
 	 * @var string
 	 */
-	$this_sdk_version = '2.6.1';
+	$this_sdk_version = '2.6.2';
 
 	#region SDK Selection Logic --------------------------------------------------------------------
 
 	/**
 	 * Special logic added on 1.1.6 to make sure that every Freemius powered plugin
diff --git a/models/model-table.php b/models/model-table.php
index b4d183c..6e17f8d 100644
--- a/models/model-table.php
+++ b/models/model-table.php
@@ -231,13 +231,15 @@ class TablePress_Table_Model extends TablePress_Model {
 		$this->model_post->load_posts( array_values( $table_post ), $prime_meta_cache );
 
 		// This loop now uses the WP cache.
 		$table_ids = array();
 		foreach ( $table_post as $table_id => $post_id ) {
-			$table_id = (string) $table_id;
+			$table_id = (string) $table_id; // Ensure that the table ID is a string, as it comes from an array key where numeric strings are converted to integers.
+
 			// Load table without data and options to save memory.
 			$table = $this->load( $table_id, false, false );
+
 			// Skip tables that could not be loaded properly.
 			if ( ! is_wp_error( $table ) ) {
 				$table_ids[] = $table_id;
 			}
 		}
@@ -525,13 +527,15 @@ class TablePress_Table_Model extends TablePress_Model {
 		if ( empty( $tables['table_post'] ) ) {
 			return;
 		}
 
 		foreach ( $tables['table_post'] as $table_id => $post_id ) {
-			$table_id = (string) $table_id;
+			$table_id = (string) $table_id; // Ensure that the table ID is a string, as it comes from an array key where numeric strings are converted to integers.
+
 			$this->model_post->delete( $post_id ); // Post Meta fields will be deleted automatically by that function.
 			unset( $tables['table_post'][ $table_id ] );
+
 			// Invalidate table output caches that belong to this table.
 			$this->invalidate_table_output_cache( $table_id );
 		}
 
 		$this->tables->update( $tables );
@@ -1056,11 +1060,11 @@ class TablePress_Table_Model extends TablePress_Model {
 
 		// Get default Table with default Table Options.
 		$default_table = $this->get_table_template();
 
 		// Go through all tables (this loop now uses the WP cache).
-		foreach ( $table_post as $table_id => $post_id ) {
+		foreach ( $table_post as $post_id ) {
 			$table_options = $this->_get_table_options( $post_id );
 			if ( $remove_old_options ) {
 				// Remove old (i.e. no longer existing) Table Options.
 				$table_options = array_intersect_key( $table_options, $default_table['options'] );
 			}
@@ -1080,10 +1084,11 @@ class TablePress_Table_Model extends TablePress_Model {
 		if ( empty( $table_post ) ) {
 			return;
 		}
 
 		foreach ( $table_post as $table_id => $post_id ) {
+			$table_id = (string) $table_id; // Ensure that the table ID is a string, as it comes from an array key where numeric strings are converted to integers.
 			$this->invalidate_table_output_cache( $table_id );
 		}
 	}
 
 	/**
diff --git a/package-lock.json b/package-lock.json
index 703b077..3e7891f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,14 +1,14 @@
 {
 	"name": "@tablepress/tablepress",
-	"version": "2.2.4",
+	"version": "2.2.5",
 	"lockfileVersion": 3,
 	"requires": true,
 	"packages": {
 		"": {
 			"name": "@tablepress/tablepress",
-			"version": "2.2.4",
+			"version": "2.2.5",
 			"license": "GPL-2.0-only",
 			"devDependencies": {
 				"@wordpress/icons": "^9.36.0",
 				"@wordpress/scripts": "^26.16.0",
 				"autoprefixer": "^9.8.8",
diff --git a/package.json b/package.json
index 1f78c22..2df772c 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
 {
 	"name": "@tablepress/tablepress",
-	"version": "2.2.4",
+	"version": "2.2.5",
 	"description": "Embed beautiful and feature-rich tables into your posts and pages, without having to write code.",
 	"author": "Tobias Bäthge",
 	"license": "GPL-2.0-only",
 	"private": true,
 	"keywords": [
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index a606598..056cc17 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -11,10 +11,12 @@ parameters:
 		- tablepress.php
 	scanDirectories:
 		- libraries/
 	bootstrapFiles:
 		- .phpstan/symbols.php
+	dynamicConstantNames:
+		- TABLEPRESS_IS_PLAYGROUND_PREVIEW
 	earlyTerminatingMethodCalls:
 		TablePress:
 			- redirect
 	ignoreErrors:
 		# The `TablePress_View` and its extended classes must not have a return type, for BC reasons.
diff --git a/readme.md b/readme.md
index e38bad8..fbdcc54 100644
--- a/readme.md
+++ b/readme.md
@@ -66,10 +66,11 @@ To make TablePress available in your language, go to the [TablePress translation
 
 After installing the plugin, you can create and manage tables on the “TablePress” screen in the WordPress Dashboard.
 
 To insert a table into a post or page, add a “TablePress table” block in the block editor and select the desired table.
 
+Beginner-friendly step-by-step [tutorials, guides, and how-tos](https://tablepress.org/tutorials/) show how to achieve common and popular tasks with TablePress.
 Examples for common styling changes via “Custom CSS” code can be found on the [TablePress FAQ page](https://tablepress.org/faq/).
 You may also add certain features (like sorting, pagination, filtering, alternating row colors, row highlighting, print name and/or description, ...) by enabling the corresponding checkboxes on a table’s “Edit” screen.
 
 **Even more great features for you and your site’s visitors and priority email support are available with a Premium license plan of TablePress. [Go check them out!](https://tablepress.org/premium/)**
 
diff --git a/readme.txt b/readme.txt
index 9040623..8380071 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,13 +1,13 @@
 === TablePress - Tables in WordPress made easy ===
 Contributors: TobiasBg
 Donate link: https://tablepress.org/premium/?utm_source=wordpress.org&utm_medium=textlink&utm_content=donate-link
-Tags: table,spreadsheet,data,csv,excel,html,tables
+Tags: table, spreadsheet, csv, excel, tables
 Requires at least: 6.0
 Requires PHP: 7.2
 Tested up to: 6.4
-Stable tag: 2.2.4
+Stable tag: 2.2.5
 License: GPLv2
 License URI: https://www.gnu.org/licenses/gpl-2.0.html
 
 Embed beautiful and interactive tables into your WordPress website’s posts and pages, without having to write code!
 
@@ -95,19 +95,32 @@ Visit the plugin website at [tablepress.org](https://tablepress.org/) for the la
 
 After installing the plugin, you can create and manage tables on the "TablePress" screen in the WordPress Dashboard.
 
 To insert a table into a post or page, add a "TablePress table" block in the block editor and select the desired table or use Shortcodes with common page builders.
 
+Beginner-friendly step-by-step [tutorials, guides, and how-tos](https://tablepress.org/tutorials/) show how to achieve common and popular tasks with TablePress.
 Examples for common styling changes via "Custom CSS" code can be found on the [TablePress FAQ page](https://tablepress.org/faq/).
 You may also add certain features (like sorting, pagination, filtering, alternating row colors, row highlighting, print name and/or description, ...) by enabling the corresponding checkboxes on a table's "Edit" screen.
 
 **Even more great features for you and your site’s visitors and priority email support are available with a Premium license plan of TablePress. [Go check them out!](https://tablepress.org/premium/?utm_source=wordpress.org&utm_medium=textlink&utm_content=readme)**
 
 == Changelog ==
 
 Changes in recent versions are shown below. For earlier changes, please see the [changelog history](https://tablepress.org/info/#changelog).
 
+= Version 2.2.5 (January 30, 2024) =
+
+* *Security fix*: The URL import now properly blocks hosts of cloud providers’ metadata API endpoints to prevent data extraction.
+* When importing a table in the Excel format, floating point numbers are now detected and handled more reliably.
+* The detection of the JSON format when importing a table is now more reliable.
+* The “Copy”, “Export”, and “Delete” buttons/links on a table’s “Edit” screen now work again after a table ID was changed.
+* Error messages when a table could not be found and similar are now shown properly in modern themes.
+* The “Automatic Filtering” feature module now also allows using a slash in the filter term. (TablePress Pro and Max only.)
+* The “Debug and Version Information” section was cleaned up and updated with more relevant checks.
+* Updated external libraries to benefit from enhancements and bug fixes.
+* Cleaned up and simplified code, for easier future maintenance, to follow WordPress Coding Standards, and to offer helpful inline documentation.
+
 = Version 2.2.4 (December 11, 2023) =
 
 * The math formula calculation engine now properly handles quotation marks in text around embedded formulas.
 * An issue with the block theme preview when using the Site Editor on multisite installations was fixed.
 * Data consistency when saving tables is checked more thorougly.
@@ -130,15 +143,15 @@ Changes in recent versions are shown below. For earlier changes, please see the
 * Further protection against bugs in other plugins that interfere with the loading of JavaScript files, causing the TablePress admin screens to be unusable, was added.
 * The code that evaluates Shortcode parameters was optimized for a higher performance.
 * The “Sorted” order of the “Row Order” premium feature module no longer raises an error. (TablePress Pro and Max only.)
 * Updated external libraries to benefit from enhancements and bug fixes.
 
-= Version 2.2.1 (November 2, 2023)=
+= Version 2.2.1 (November 2, 2023) =
 
 * Further protection against bugs in other plugins that interfere with the loading of JavaScript files, causing the TablePress admin screens to be unusable, was added.
 
-= Version 2.2 (November 2, 2023)=
+= Version 2.2 (November 2, 2023) =
 
 **Improvements around table styling**
 
 * The preview of the TablePress table block in the block editor now takes into account “Custom CSS”, for a more precise preview.
 * TablePress Pro and Max now have an **easy-to-use visual “Default Style Customizer”**: Choose from pre-defined style variations or define your own color scheme to change your tables’ default style -- without touching CSS code!
@@ -173,10 +186,10 @@ Changes in recent versions are shown below. For earlier changes, please see the
 
 * Even more great features for you and your site’s visitors and priority email support are available with a Premium license plan of TablePress. [Go check them out!](https://tablepress.org/premium/?utm_source=wordpress.org&utm_medium=textlink&utm_content=readme)
 
 == Upgrade Notice ==
 
-= 2.2.4 =
-This update is a stability and maintenance release. Updating is highly recommended.
+= 2.2.5 =
+This update is a security and maintenance release. Updating is highly recommended.
 
 = 2.2 =
 This update is a feature, stability, maintenance, and compatibility release. Updating is highly recommended.
diff --git a/tablepress.php b/tablepress.php
index 35e8046..221f707 100644
--- a/tablepress.php
+++ b/tablepress.php
@@ -2,27 +2,27 @@
 /**
  * WordPress plugin "TablePress" main file, responsible for initiating the plugin.
  *
  * @package TablePress
  * @author Tobias Bäthge
- * @version 2.2.4
+ * @version 2.2.5
  *
  *
  * Plugin Name: TablePress
  * Plugin URI: https://tablepress.org/
  * Description: Embed beautiful and interactive tables into your WordPress website’s posts and pages, without having to write code!
- * Version: 2.2.4
+ * Version: 2.2.5
  * Requires at least: 6.0
  * Requires PHP: 7.2
  * Author: Tobias Bäthge
  * Author URI: https://tablepress.org/
  * Author email: wordpress@tobias.baethge.com
  * License: GPL 2
  * Donate URI: https://tablepress.org/donate/
  *
  *
- * Copyright 2012-2023 Tobias Bäthge
+ * Copyright 2012-2024 Tobias Bäthge
  *
  * TablePress is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, version 2, as published by
  * the Free Software Foundation.
  *
@@ -38,10 +38,14 @@
  */
 
 // Prohibit direct script loading.
 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
 
+if ( ! defined( 'TABLEPRESS_IS_PLAYGROUND_PREVIEW' ) ) {
+	define( 'TABLEPRESS_IS_PLAYGROUND_PREVIEW', false );
+}
+
 if ( function_exists( 'tb_tp_fs' ) ) {
 	tb_tp_fs()->set_basename( false, __FILE__ ); // @phpstan-ignore-line
 } else {
 	/**
 	 * Helper function for easier Freemius SDK access.
@@ -76,10 +80,11 @@ if ( function_exists( 'tb_tp_fs' ) ) {
 					'new'       => true,
 					'updates'   => false,
 					'localhost' => false,
 				),
 				'is_live'           => true,
+				'anonymous_mode'    => TABLEPRESS_IS_PLAYGROUND_PREVIEW,
 			) );
 		}
 
 		return $tb_tp_fs;
 	}
diff --git a/tests/data/import/phpspreadsheet/test-table.xlsx b/tests/data/import/phpspreadsheet/test-table.xlsx
index 680d941..96d988d 100644
Binary files a/tests/data/import/phpspreadsheet/test-table.xlsx and b/tests/data/import/phpspreadsheet/test-table.xlsx differ
diff --git a/tests/test-tablepress_import.php b/tests/test-tablepress_import.php
index 6f29e8b..c46a53e 100644
--- a/tests/test-tablepress_import.php
+++ b/tests/test-tablepress_import.php
@@ -135,11 +135,11 @@ class TablePress_Test_TablePress_Import extends TablePress_TestCase {
 			array( '   Text   ', '   Text   ', 'Three spaces before and after text', '   Text   ' ),
 			array( '123', '123', 'Integer', '123' ),
 			array( '1230', '1230', 'Integer with trailing zero', '1230' ),
 			array( '0123', '0123', 'Integer with leading zero', '0123' ),
 			array( '   123   ', '   123   ', 'Three spaces before and after an integer', '   123   ' ),
-			array( '123.5', '123.5', 'Float', '123.5' ),
+			array( '123.5', '123.5', 'Float with comma and period', '123.5' ),
 			array( '0123.5', '0123.5', 'Float with leading zero', '0123.5' ),
 			array( '123.50', '123.50', 'Float with trailing zero', '123.50' ),
 			array( '0123.50', '0123.50', 'Float with leading and trailing zero', '0123.50' ),
 			array( '123,5', '123,5', 'Float with comma', '123,5' ),
 			array( '0123,5', '0123,5', 'Float with comma with leading zero', '0123,5' ),
@@ -175,10 +175,12 @@ class TablePress_Test_TablePress_Import extends TablePress_TestCase {
 			array( '<span style="color:#FF0000;">red text</span>', 'yellow background', 'right aligned', '' ),
 			array( "Cell comment<div class=\"comment\">Microsoft Office User:\nComment text</div>", 'CO<strong><sub>2</sub></strong> subscript bold', 'center aligned', '' ),
 			array( '<span style="color:#FF0000;">red text <span style="color:#FFFF00;">yellow text</span></span>', 'H<sub>2</sub>O', 'left aligned', '' ),
 			array( '', 'H<sub>2</sub>O <span style="color:#00FA00;">green</span>', '<span style="color:#0432FF;">H<span style="color:#0432FF;"><sub>2</sub></span><span style="color:#0432FF;">O </span><span style="color:#FF2600;">gr</span>e<span style="color:#FF2600;">en</span></span>', '' ),
 			array( '1', '2', 'Styled formula does not get inline HTML after import', '=A61+B61' ),
+			array( '3.022', '-0.162', 'Floats that can cause floating point precision errors with the General format 1', '0.579' ),
+			array( '-3.022', '-0.051', 'Floats that can cause floating point precision errors with the General format 2', '0.094' ),
 		);
 
 		$this->assertSame( $expected_table_data, $imported_table_data );
 	}
 
diff --git a/views/view-about.php b/views/view-about.php
index 5d6d285..9512b5f 100644
--- a/views/view-about.php
+++ b/views/view-about.php
@@ -203,11 +203,10 @@ class TablePress_About_View extends TablePress_View {
 	 *
 	 * @param array<string, mixed> $data Data for this screen.
 	 * @param array<string, mixed> $box  Information about the meta box.
 	 */
 	public function postbox_debug_version_information( array $data, array $box ): void {
-		$mysqli = ( isset( $GLOBALS['wpdb']->use_mysqli, $GLOBALS['wpdb']->dbh ) && $GLOBALS['wpdb']->use_mysqli );
 		?>
 		<p>
 			<strong><?php _e( 'Please provide this information in bug reports and support requests.', 'tablepress' ); ?></strong>
 		</p>
 		<p class="ltr">
@@ -218,15 +217,18 @@ class TablePress_About_View extends TablePress_View {
 			<br />&middot; Plan: Free
 			<br />&middot; Plugin installed: <?php echo wp_date( 'Y/m/d H:i:s', $data['first_activation'] ); ?>
 			<br />&middot; WordPress: <?php echo $GLOBALS['wp_version']; ?>
 			<br />&middot; Multisite: <?php echo is_multisite() ? 'yes' : 'no'; ?>
 			<br />&middot; PHP: <?php echo PHP_VERSION; ?>
-			<br />&middot; mysqli Extension: <?php echo $mysqli ? 'true' : 'false'; ?>
-			<br />&middot; mySQL (Server): <?php echo $mysqli ? mysqli_get_server_info( $GLOBALS['wpdb']->dbh ) : '<em>no mysqli</em>'; // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info ?>
-			<br />&middot; mySQL (Client): <?php echo $mysqli ? mysqli_get_client_info() : '<em>no mysqli</em>'; // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_client_info ?>
-			<br />&middot; ZIP support: <?php echo $data['zip_support_available'] ? 'yes' : 'no'; ?>
-			<br />&middot; UTF-8 conversion: <?php echo ( function_exists( 'mb_detect_encoding' ) && function_exists( 'iconv' ) ) ? 'yes' : 'no'; ?>
+			<br />&middot; mySQL (Server): <?php echo isset( $GLOBALS['wpdb']->dbh ) ? mysqli_get_server_info( $GLOBALS['wpdb']->dbh ) : 'wpdb::$dbh not set'; // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info ?>
+			<br />&middot; mySQL (Client): <?php echo mysqli_get_client_info(); // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_client_info ?>
+			<br />&middot; mbstring: <?php echo extension_loaded( 'mbstring' ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
+			<br />&middot; ZipArchive: <?php echo class_exists( 'ZipArchive', false ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
+			<br />&middot; DOMDocument: <?php echo class_exists( 'DOMDocument', false ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
+			<br />&middot; simplexml_load_string: <?php echo function_exists( 'simplexml_load_string' ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
+			<br />&middot; libxml_disable_entity_loader: <?php echo function_exists( 'libxml_disable_entity_loader' ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
+			<br />&middot; UTF-8 conversion: <?php echo ( function_exists( 'mb_detect_encoding' ) && function_exists( 'iconv' ) ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
 			<br />&middot; WP Memory Limit: <?php echo WP_MEMORY_LIMIT; ?>
 			<br />&middot; Server Memory Limit: <?php echo (int) @ini_get( 'memory_limit' ) . 'M'; // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged ?>
 			<br />&middot; WP_DEBUG: <?php echo WP_DEBUG ? 'true' : 'false'; ?>
 			<br />&middot; WP_POST_REVISIONS: <?php echo is_bool( WP_POST_REVISIONS ) ? ( WP_POST_REVISIONS ? 'true' : 'false' ) : WP_POST_REVISIONS; // @phpstan-ignore-line ?>
 		</p>
diff --git a/views/view-edit.php b/views/view-edit.php
index 040a75d..c67f2b8 100644
--- a/views/view-edit.php
+++ b/views/view-edit.php
@@ -64,11 +64,11 @@ class TablePress_Edit_View extends TablePress_View {
 		wp_enqueue_media();
 		wp_enqueue_script( 'wplink' ); // JS for the "Insert Link" button.
 		$this->admin_page->enqueue_style( 'jspreadsheet' );
 		$this->admin_page->enqueue_style( 'jsuites', array( 'tablepress-jspreadsheet' ) );
 		$this->admin_page->enqueue_style( 'edit', array( 'tablepress-jspreadsheet', 'tablepress-jsuites' ) );
-		if ( tb_tp_fs()->is_free_plan() ) {
+		if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) {
 			$this->admin_page->enqueue_style( 'edit-features', array( 'tablepress-edit' ) );
 		}
 		$this->admin_page->enqueue_script( 'jspreadsheet' );
 		$this->admin_page->enqueue_script( 'jsuites', array( 'tablepress-jspreadsheet' ) );
 		$this->admin_page->enqueue_script( 'edit', array( 'tablepress-jspreadsheet', 'tablepress-jsuites', 'jquery-core' ) );
@@ -231,11 +231,11 @@ class TablePress_Edit_View extends TablePress_View {
 		<th class="column-1" scope="row"><?php _e( 'Last Modified', 'tablepress' ); ?>:</th>
 		<td class="column-2"><?php printf( __( '%1$s by %2$s', 'tablepress' ), '<span id="last-modified">' . TablePress::format_datetime( $data['table']['last_modified'] ) . '</span>', '<span id="last-editor">' . TablePress::get_user_display_name( $data['table']['options']['last_editor'] ) . '</span>' ); ?></td>
 	</tr>
 </table>
 		<?php
-		if ( tb_tp_fs()->is_free_plan() ) :
+		if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) :
 			?>
 			<div class="postbox premium-features">
 				<div>
 					<div>
 						<div class="postbox-header">
@@ -279,10 +279,12 @@ class TablePress_Edit_View extends TablePress_View {
 		echo "window.tp = window.tp || {};\n";
 
 		echo "tp.nonces = {};\n";
 		echo "tp.nonces.edit_table = '" . wp_create_nonce( TablePress::nonce( $this->action, $data['table']['id'] ) ) . "';\n";
 		echo "tp.nonces.preview_table = '" . wp_create_nonce( TablePress::nonce( 'preview_table', $data['table']['id'] ) ) . "';\n";
+		echo "tp.nonces.copy_table = '" . wp_create_nonce( TablePress::nonce( 'copy_table', $data['table']['id'] ) ) . "';\n";
+		echo "tp.nonces.delete_table = '" . wp_create_nonce( TablePress::nonce( 'delete_table', $data['table']['id'] ) ) . "';\n";
 		echo "tp.nonces.screen_options = '" . wp_create_nonce( TablePress::nonce( 'screen_options' ) ) . "';\n";
 
 		echo "tp.table = {};\n";
 		echo "tp.table.shortcode = '" . esc_js( TablePress::$shortcode ) . "';\n";
 		echo "tp.table.id = '{$data['table']['id']}';\n";
@@ -389,11 +391,11 @@ class TablePress_Edit_View extends TablePress_View {
 	public function textbox_buttons( array $data, array $box ): void {
 		$preview_url = TablePress::url( array( 'action' => 'preview_table', 'item' => $data['table']['id'], 'return' => 'edit', 'return_item' => $data['table']['id'] ), true, 'admin-post.php' );
 
 		echo '<p id="' . $box['id'] . '-submit" class="submit">';
 		if ( current_user_can( 'tablepress_preview_table', $data['table']['id'] ) ) {
-			echo '<a href="' . $preview_url . '" class="button button-large button-show-preview" target="_blank" data-shortcut="' . esc_attr( _x( '%1$sP', 'keyboard shortcut for Preview', 'tablepress' ) ) . '">' . __( 'Preview', 'tablepress' ) . '</a>';
+			echo '<a href="' . $preview_url . '" class="button button-large button-preview" target="_blank" data-shortcut="' . esc_attr( _x( '%1$sP', 'keyboard shortcut for Preview', 'tablepress' ) ) . '">' . __( 'Preview', 'tablepress' ) . '</a>';
 		}
 		?>
 			<input type="button" class="button button-primary button-large button-save-changes" value="<?php esc_attr_e( 'Save Changes', 'tablepress' ); ?>" data-shortcut="<?php echo esc_attr( _x( '%1$sS', 'keyboard shortcut for Save Changes', 'tablepress' ) ); ?>" />
 		<?php
 		echo '</p>';
@@ -417,17 +419,17 @@ class TablePress_Edit_View extends TablePress_View {
 		}
 
 		echo '<p class="submit">';
 		echo __( 'Other Actions', 'tablepress' ) . ':&nbsp; ';
 		if ( $user_can_copy_table ) {
-			echo '<a href="' . TablePress::url( array( 'action' => 'copy_table', 'item' => $data['table']['id'], 'return' => 'edit' ), true, 'admin-post.php' ) . '" class="button">' . __( 'Copy Table', 'tablepress' ) . '</a> ';
+			echo '<a href="' . TablePress::url( array( 'action' => 'copy_table', 'item' => $data['table']['id'], 'return' => 'edit' ), true, 'admin-post.php' ) . '" class="button button-copy">' . __( 'Copy Table', 'tablepress' ) . '</a> ';
 		}
 		if ( $user_can_export_table ) {
-			echo '<a href="' . TablePress::url( array( 'action' => 'export', 'table_id' => $data['table']['id'] ) ) . '" class="button">' . __( 'Export Table', 'tablepress' ) . '</a> ';
+			echo '<a href="' . TablePress::url( array( 'action' => 'export', 'table_id' => $data['table']['id'] ) ) . '" class="button button-export">' . __( 'Export Table', 'tablepress' ) . '</a> ';
 		}
 		if ( $user_can_delete_table ) {
-			echo '<a href="' . TablePress::url( array( 'action' => 'delete_table', 'item' => $data['table']['id'], 'return' => 'edit', 'return_item' => $data['table']['id'] ), true, 'admin-post.php' ) . '" class="button delete-link">' . __( 'Delete Table', 'tablepress' ) . '</a>';
+			echo '<a href="' . TablePress::url( array( 'action' => 'delete_table', 'item' => $data['table']['id'], 'return' => 'edit', 'return_item' => $data['table']['id'] ), true, 'admin-post.php' ) . '" class="button button-delete delete-link">' . __( 'Delete Table', 'tablepress' ) . '</a>';
 		}
 		echo '</p>';
 	}
 
 	/**
diff --git a/views/view-editor_button_thickbox.php b/views/view-editor_button_thickbox.php
index e57f552..f07c308 100644
--- a/views/view-editor_button_thickbox.php
+++ b/views/view-editor_button_thickbox.php
@@ -123,11 +123,11 @@ html {
 		<?php
 		if ( ! empty( $_GET['s'] ) ) {
 			printf( '<span class="subtitle">' . __( 'Search results for &#8220;%s&#8221;', 'tablepress' ) . '</span>', esc_html( wp_unslash( $_GET['s'] ) ) );
 		}
 		?>
-<form method="get" action="">
+<form method="get">
 	<input type="hidden" name="action" value="tablepress_<?php echo $this->action; ?>" />
 		<?php
 		wp_nonce_field( TablePress::nonce( $this->action ), '_wpnonce', false );
 		$this->wp_list_table->search_box( __( 'Search Tables', 'tablepress' ), 'tables_search' );
 		?>
diff --git a/views/view-list.php b/views/view-list.php
index 815c7b0..909de1c 100644
--- a/views/view-list.php
+++ b/views/view-list.php
@@ -209,11 +209,11 @@ class TablePress_List_View extends TablePress_View {
 	public function textbox_tables_list( array $data, array $box ): void {
 		if ( ! empty( $_GET['s'] ) ) {
 			printf( '<span class="subtitle">' . __( 'Search results for &#8220;%s&#8221;', 'tablepress' ) . '</span>', esc_html( wp_unslash( $_GET['s'] ) ) );
 		}
 		?>
-<form method="get" action="">
+<form method="get">
 		<?php
 		if ( isset( $_GET['page'] ) ) {
 			echo '<input type="hidden" name="page" value="' . esc_attr( $_GET['page'] ) . '" />' . "\n";
 		}
 		$this->wp_list_table->search_box( __( 'Search Tables', 'tablepress' ), 'tables_search' );

Vulnerable code: /package.json export-ignore
<?php return array('dependencies' => array('wp-hooks', 'wp-i18n', 'wp-url'), 'version' => 'cdf1475bc9e3883381b2');
!function(){"use strict";var e=window.wp.i18n,t=window.wp.hooks,s=window.wp.url;const o=e=>"#"===e[0]?document.getElementById(e.slice(1)):document.querySelectorAll(e);window.tp=window.tp||{},tp.made_changes=!1,tp.helpers=tp.helpers||{},tp.callbacks=tp.callbacks||{},tp.helpers.selection=tp.helpers.selection||{rows:[0],columns:[0]},tp.helpers.unsaved_changes=tp.helpers.unsaved_changes||{},tp.helpers.unsaved_changes.unload_dialog=function(e){e.preventDefault(),e.returnValue=""},tp.helpers.unsaved_changes.set=function(){tp.made_changes||(tp.made_changes=!0,window.addEventListener("beforeunload",tp.helpers.unsaved_changes.unload_dialog))},tp.helpers.unsaved_changes.unset=function(){tp.made_changes=!1,window.removeEventListener("beforeunload",tp.helpers.unsaved_changes.unload_dialog)},tp.helpers.options=tp.helpers.options||{},tp.helpers.options.load=function(){Object.keys(tp.table.options).forEach((function(e){if("last_editor"===e)return;if(""===(e=(0,t.applyFilters)("tablepress.optionsLoad",e)))return;let s=o(`#option-${e}`);s||(s=o(`#option-${e}-${tp.table.options[e]}`)),s&&(s instanceof HTMLInputElement&&"checkbox"===s.type?s.checked=tp.table.options[e]:s instanceof HTMLInputElement&&"radio"===s.type?s.checked=!0:s.value=tp.table.options[e])})),tp.table.options.use_datatables&&tp.helpers.editor.has_merged_cells()&&(tp.table.options.use_datatables=!1,o("#option-use_datatables").checked=!1),tp.helpers.options.check_dependencies()},tp.helpers.options.change=function(s){if(!s.target)return;const l=s.target.name||"";if(""===l)return;const a=s.target instanceof HTMLInputElement&&"checkbox"===s.target.type?"checked":"value";tp.table.options[l]=s.target[a],s.target instanceof HTMLInputElement&&"number"===s.target.type&&(tp.table.options[l]=parseInt(tp.table.options[l],10)),"use_datatables"===l&&tp.table.options.use_datatables&&tp.helpers.editor.has_merged_cells()&&(tp.table.options.use_datatables=!1,o("#option-use_datatables").checked=!1,window.alert((0,e.__)("You can not enable the Table Features for Site Visitors, because your table contains combined/merged cells.","tablepress"))),(0,t.doAction)("tablepress.optionsChange",l,a,s),tp.helpers.options.check_dependencies(),tp.helpers.unsaved_changes.set(),tp.editor.updateTable()},tp.helpers.options.check_dependencies=function(){o("#option-use_datatables").disabled=!tp.table.options.table_head,o("#notice-datatables-head-row").style.display=tp.table.options.table_head?"none":"block",o("#option-print_name_position").disabled=!tp.table.options.print_name,o("#option-print_description_position").disabled=!tp.table.options.print_description;const e=tp.table.options.use_datatables&&tp.table.options.table_head;o("#tablepress_edit-datatables-features").querySelectorAll(":scope input:not(#option-use_datatables), :scope textarea").forEach((t=>t.disabled=!e));const s=e&&tp.table.options.datatables_paginate;o("#option-datatables_lengthchange").disabled=!s,o("#option-datatables_paginate_entries").disabled=!s,(0,t.doAction)("tablepress.optionsCheckDependencies")},tp.helpers.options.validate_fields=function(){if(tp.table.options.datatables_paginate&&(isNaN(tp.table.options.datatables_paginate_entries)||tp.table.options.datatables_paginate_entries<1||tp.table.options.datatables_paginate_entries>9999)){window.alert((0,e.sprintf)((0,e.__)("The entered value in the “%1$s” field is invalid.","tablepress"),(0,e.__)("Pagination Entries","tablepress")));const t=o("#option-datatables_paginate_entries");return t.focus(),t.select(),!1}if(/[^A-Za-z0-9- _:]/.test(tp.table.options.extra_css_classes)){window.alert((0,e.sprintf)((0,e.__)("The entered value in the “%1$s” field is invalid.","tablepress"),(0,e.__)("Extra CSS Classes","tablepress")));const t=o("#option-extra_css_classes");return t.focus(),t.select(),!1}return(0,t.applyFilters)("tablepress.optionsValidateFields",!0)},tp.helpers.visibility=tp.helpers.visibility||{},tp.helpers.visibility.load=function(){const e=tp.table.visibility.rows.length,t=tp.table.visibility.columns.length,s={};for(let o=0;o<e;o++)if(1!==tp.table.visibility.rows[o])for(let e=0;e<t;e++){const t=jspreadsheet.getColumnNameFromId([e,o]);s[t]=s[t]||{},s[t].row_hidden=!0}for(let o=0;o<t;o++)if(1!==tp.table.visibility.columns[o])for(let t=0;t<e;t++){const e=jspreadsheet.getColumnNameFromId([o,t]);s[e]=s[e]||{},s[e].column_hidden=!0}return s},tp.helpers.visibility.update=function(){tp.table.visibility.rows=[];for(let e=0;e<tp.editor.options.data.length;e++)tp.table.visibility.rows[e]=1;tp.table.visibility.columns=[];for(let e=0;e<tp.editor.options.columns.length;e++)tp.table.visibility.columns[e]=1;Object.keys(tp.editor.options.meta).forEach((function(e){const t=jspreadsheet.getIdFromColumnName(e,!0);1===tp.table.visibility.rows[t[1]]&&tp.editor.options.meta[e].row_hidden&&(tp.table.visibility.rows[t[1]]=0),1===tp.table.visibility.columns[t[0]]&&tp.editor.options.meta[e].column_hidden&&(tp.table.visibility.columns[t[0]]=0)}))},tp.helpers.visibility.selection_contains=function(e,t){return tp.helpers.selection[e].some((s=>tp.table.visibility[e][s]===t))},tp.helpers.move_allowed=function(e,t){let s=tp.helpers.selection[e][0],o=0;return"down"!==t&&"right"!==t&&"bottom"!==t&&"last"!==t||(s=tp.helpers.selection[e][tp.helpers.selection[e].length-1],o="rows"===e?tp.editor.options.data.length-1:tp.editor.options.columns.length-1),o!==s},tp.helpers.cell_merge_allowed=function(t,s={}){const o="alert"===t;if(tp.table.options.table_head&&tp.table.options.use_datatables)return s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Enable Visitor Features","tablepress"),(0,e.__)("Table Features for Site Visitors","tablepress"))+" "+(0,e.__)("The Table Features for Site Visitors are not compatible with merged cells.","tablepress"),o&&window.alert(s.text),!1;const l=tp.helpers.selection.rows[0],a=tp.helpers.selection.rows[tp.helpers.selection.rows.length-1];if(tp.table.options.table_head&&0===l&&a>0)return s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Table Head Row","tablepress"),(0,e.__)("Table Options","tablepress")),o&&window.alert(s.text),!1;const n=tp.editor.options.data.length-1;return!(tp.table.options.table_foot&&n===a&&l<n&&(s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Table Foot Row","tablepress"),(0,e.__)("Table Options","tablepress")),o&&window.alert(s.text),1))},tp.helpers.editor=tp.helpers.editor||{},tp.helpers.editor.reselect=function(e,t){void 0===t&&(t=tp.editor),t.updateSelectionFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],tp.helpers.selection.columns[tp.helpers.selection.columns.length-1],tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.helpers.editor.has_merged_cells=function(){const e=tp.editor.options.data.length,t=tp.editor.options.columns.length;for(let s=1;s<e;s++)for(let e=1;e<t;e++)if("#rowspan#"===tp.editor.options.data[s][e]||"#colspan#"===tp.editor.options.data[s][e])return!0;return!1},tp.helpers.editor.sorting=function(e){return e=e?-1:1,function(t,s){return e*((e,t)=>{const s=/(^([+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|^0x[\da-fA-F]+$|\d+)/g,o=/^\s+|\s+$/g,l=/\s+/g,a=/^0x[0-9a-f]+$/i,n=/^0/,i=e.replace(o,"")||"",r=t.replace(o,"")||"",c=i.replace(s,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0"),p=r.replace(s,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0"),d=parseInt(i.match(a),16)||1!==c.length&&Date.parse(i),u=parseInt(r.match(a),16)||d&&r.match(/(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/)&&Date.parse(r)||null,b=(e,t)=>(!e.match(n)||1===t)&&parseFloat(e)||e.replace(l," ").replace(o,"")||0;if(u){if(d<u)return-1;if(d>u)return 1}for(let e=0,t=c.length,s=p.length,o=Math.max(t,s);e<o;e++){const o=b(c[e]||"",t),l=b(p[e]||"",s);if(isNaN(o)!==isNaN(l))return isNaN(o)?1:-1;if(/[^\x00-\x80]/.test(o+l)&&o.localeCompare){const e=o.localeCompare(l);return e/Math.abs(e)}if(o<l)return-1;if(o>l)return 1}return 0})(t[1],s[1])}},tp.callbacks.editor=tp.callbacks.editor||{},tp.callbacks.editor.onselection=function(e,t,s,o,l){tp.helpers.selection={rows:[],columns:[]};for(let e=s;e<=l;e++)tp.helpers.selection.rows.push(e);for(let e=t;e<=o;e++)tp.helpers.selection.columns.push(e)},tp.callbacks.editor.onupdatetable=function(e,t,s,o,l,a,n){const i=e.jspreadsheet.options.meta[n];if(t.classList.toggle("column-hidden",Boolean(i?.column_hidden)),0===s&&(t.parentNode.classList.toggle("row-hidden",Boolean(i?.row_hidden)),t.parentNode.classList.remove("head-row","foot-row"),o===e.jspreadsheet.rows.length-1)){const t=e.jspreadsheet.content.querySelectorAll(":scope tbody tr:not(.row-hidden)");1<t.length&&(tp.table.options.table_head&&t[0].classList.add("head-row"),tp.table.options.table_foot&&t[t.length-1].classList.add("foot-row"))}},tp.callbacks.editor.oninsertroc=function(e,t,s,o,l,a,n){const i="rows"===e,r=i?"column_hidden":"row_hidden",c="duplicate"===t,p=o+(n?l:0),d=i?tp.editor.options.columns.length:tp.editor.options.data.length,u={};for(let e=0;e<d;e++){const t=i?[e,p]:[p,e],s=tp.editor.options.meta[jspreadsheet.getColumnNameFromId(t)];s&&(c?u[e]=s:s[r]&&(u[e]=u[e]||{},u[e][r]=!0))}const b=Object.keys(u);if(!b.length)return;const h={};n||o++;for(let e=0;e<l;e++){const t=o+e;b.forEach((function(e){const s=i?[e,t]:[t,e];h[jspreadsheet.getColumnNameFromId(s)]=u[e]}))}tp.editor.setMeta(h),tp.editor.updateTable()},tp.callbacks.editor.onmove=function(){tp.helpers.editor.reselect(),tp.helpers.unsaved_changes.set()},tp.callbacks.editor.onsort=function(){tp.editor.updateTable(),tp.helpers.unsaved_changes.set()},tp.helpers.editor.insert_from_helper_textarea=function(){tp.editor.setValueFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],this.value)},tp.callbacks.insert_link={},tp.callbacks.insert_link.open_dialog=function(t=null){const s=o("#textarea-insert-helper");s.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]],t?(s.selectionStart=t.selectionStart,s.selectionEnd=t.selectionEnd):(s.selectionStart=s.value.length,s.selectionEnd=s.value.length);const l=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]);o("#link-modal-title").textContent=(0,e.sprintf)((0,e.__)("Insert Link into cell %1$s","tablepress"),l),wpLink.open("textarea-insert-helper"),jexcel.current=null},tp.callbacks.insert_image={},tp.callbacks.insert_image.open_dialog=function(t=null){const s=o("#textarea-insert-helper");s.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]],t?(s.selectionStart=t.selectionStart,s.selectionEnd=t.selectionEnd):(s.selectionStart=s.value.length,s.selectionEnd=s.value.length),wp.media.editor.open("textarea-insert-helper",{frame:"post",state:"insert",title:wp.media.view.l10n.addMedia,multiple:!0});const l=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]);document.querySelector("#media-frame-title h1").textContent=(0,e.sprintf)((0,e.__)("Add media to cell %1$s","tablepress"),l),jexcel.current=null},tp.callbacks.advanced_editor={},tp.callbacks.advanced_editor.$textarea=o("#advanced-editor-content"),tp.callbacks.advanced_editor.open_dialog=function(t=null){tp.callbacks.advanced_editor.$textarea.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]];const s=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]),l=(0,e.sprintf)((0,e.__)("Advanced Editor for cell %1$s","tablepress"),s);o("#advanced-editor-label").textContent=l,o("#link-modal-title").textContent=(0,e.sprintf)((0,e.__)("Insert Link into cell %1$s","tablepress"),s),jQuery("#advanced-editor").wpdialog({width:600,modal:!0,title:l,resizable:!1,closeOnEscape:!0,buttons:[{text:(0,e.__)("Cancel","tablepress"),class:"button button-cancel",click(){jQuery(this).wpdialog("close")}},{text:(0,e.__)("OK","tablepress"),class:"button button-primary button-ok",click:tp.callbacks.advanced_editor.confirm_save}]}),jexcel.current=null,t?(tp.callbacks.advanced_editor.$textarea.selectionStart=t.selectionStart,tp.callbacks.advanced_editor.$textarea.selectionEnd=t.selectionEnd):(tp.callbacks.advanced_editor.$textarea.selectionStart=tp.callbacks.advanced_editor.$textarea.value.length,tp.callbacks.advanced_editor.$textarea.selectionEnd=tp.callbacks.advanced_editor.$textarea.value.length),tp.callbacks.advanced_editor.$textarea.focus()},tp.callbacks.advanced_editor.confirm_save=function(){const e=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]];tp.callbacks.advanced_editor.$textarea.value!==e&&tp.editor.setValueFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],tp.callbacks.advanced_editor.$textarea.value),jQuery(this).wpdialog("close")},tp.callbacks.help_box={},tp.callbacks.help_box.open_dialog=function(t){const s=o(t.target.dataset.helpBox);jQuery(s).wpdialog({height:s.dataset.height,width:s.dataset.width,minWidth:260,modal:!0,closeOnEscape:!0,buttons:[{text:(0,e.__)("OK","tablepress"),class:"button button-ok",click(){jQuery(this).wpdialog("close")}}],open(){jQuery(this).next().find(".button-ok").trigger("focus")}})},tp.callbacks.table_preview={},tp.callbacks.table_preview.process=function(t){t.preventDefault();let l=o("#table-name").value;if(""===l.trim()&&(l=(0,e.__)("(no name)","tablepress")),tp.callbacks.table_preview.$dialog=jQuery("#table-preview").wpdialog({autoOpen:!1,width:window.innerWidth-80,height:window.innerHeight-80,modal:!0,title:(0,e.sprintf)((0,e.__)("Preview of table “%1$s” (ID %2$s)","tablepress"),l,tp.table.id),closeOnEscape:!0,buttons:[{text:(0,e.__)("OK","tablepress"),class:"button button-ok",click(){jQuery(this).wpdialog("close")}}]}),!tp.made_changes){const e=o("#table-preview-iframe");return e.src=t.target.href,e.removeAttribute("srcdoc"),void tp.callbacks.table_preview.$dialog.wpdialog("open")}tp.helpers.visibility.update();const a={action:"tablepress_preview_table",_ajax_nonce:tp.nonces.preview_table,tablepress:{id:tp.table.id,new_id:tp.table.new_id,name:o("#table-name").value,description:o("#table-description").value,data:JSON.stringify(tp.editor.options.data),options:JSON.stringify(tp.table.options),visibility:JSON.stringify(tp.table.visibility),number:{rows:tp.editor.options.data.length,columns:tp.editor.options.columns.length}}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-table-preview" class="spinner-table-preview spinner is-active" title="${(0,e.__)("The Table Preview is being loaded …","tablepress")}"/>`),o(".button-show-preview").forEach((e=>e.classList.add("disabled"))),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(a)}).then((e=>{if(!e.ok)throw new Error(`There was a problem with the server, HTTP response code ${e.status} (${e.statusText}).`);return e.json()})).then((e=>{if(null==e||"-1"===e||void 0===e.success)throw new Error("The JSON data returned from the server is unclear or incomplete.");if(!0!==e.success)throw new Error("The preview could not be loaded.");tp.callbacks.table_preview.success(e)})).catch((e=>tp.callbacks.table_preview.error(e.message))).finally((()=>{o("#spinner-table-preview").remove(),o(".button-show-preview").forEach((e=>e.classList.remove("disabled"))),document.body.classList.remove("wait")}))},tp.callbacks.table_preview.success=function(e){const t=o("#table-preview-iframe");t.src="",t.srcdoc=`<!DOCTYPE html><html><head>${e.head_html}</head><body>${e.body_html}</body></html>`,tp.callbacks.table_preview.$dialog.wpdialog("open")},tp.callbacks.table_preview.error=function(t){t=(0,e.__)("Attention: Unfortunately, an error occurred.","tablepress")+" "+t;const s=`show-preview-${Date.now()}`;o("#spinner-table-preview").parentNode.insertAdjacentHTML("afterend",`<div id="${s}" class="ajax-alert notice notice-error"><p>${t}</p></div>`);const l=o(`#${s}`);l.offsetWidth,l.style.opacity=0,l.addEventListener("transitionend",(()=>l.remove()))},tp.callbacks.save_changes={},tp.callbacks.save_changes.process=function(t){if(!tp.helpers.options.validate_fields())return;tp.helpers.visibility.update();const l={action:"tablepress_save_table",_ajax_nonce:tp.nonces.edit_table,tablepress:{id:tp.table.id,new_id:tp.table.new_id,name:o("#table-name").value,description:o("#table-description").value,data:JSON.stringify(tp.editor.options.data),options:JSON.stringify(tp.table.options),visibility:JSON.stringify(tp.table.visibility),number:{rows:tp.editor.options.data.length,columns:tp.editor.options.columns.length}}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-save-changes" class="spinner-save-changes spinner is-active" title="${(0,e.__)("Changes are being saved …","tablepress")}"/>`),o(".button-save-changes").forEach((e=>e.disabled=!0)),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(l)}).then((e=>{if(!e.ok)throw new Error(`There was a problem with the server, HTTP response code ${e.status} (${e.statusText}).`);return e.json()})).then((t=>{if(null==t||"-1"===t||void 0===t.success)throw new Error("The JSON data returned from the server is unclear or incomplete.");if(!0!==t.success){const s=(0,e.__)("These errors were encountered:","tablepress"),o=t.error_details?`</p><p>${s}</p><pre>${t.error_details}</pre><p>`:"";throw new Error(`The table could not be saved to the database properly.${o}`)}tp.callbacks.save_changes.success(t)})).catch((e=>tp.callbacks.save_changes.error(e.message))).finally((()=>{o("#spinner-save-changes").remove(),o(".button-save-changes").forEach((e=>e.disabled=!1)),document.body.classList.remove("wait")}))},tp.callbacks.save_changes.success=function(t){tp.table.id!==t.table_id&&window?.history?.pushState&&window.history.pushState("","",window.location.href.replace(/table_id=[0-9a-zA-Z-_]+/gi,`table_id=${t.table_id}`)),tp.table.id=t.table_id,tp.table.new_id=t.table_id,o("#table-id").value=t.table_id;const s=o("#table-information-shortcode");s&&(s.value=`[${tp.table.shortcode} id=${t.table_id} /]`),tp.nonces.edit_table=t.new_edit_nonce,tp.nonces.preview_table=t.new_preview_nonce,o(".button-show-preview").forEach((e=>{e.href=e.href.replace(/item=[a-zA-Z0-9_-]+/g,`item=${t.table_id}`).replace(/&_wpnonce=[a-z0-9]+/gi,`&_wpnonce=${t.new_preview_nonce}`)})),o("#last-modified").textContent=t.last_modified,o("#last-editor").textContent=t.last_editor,tp.helpers.unsaved_changes.unset();const l={};if(l.success_save=(0,e.__)("The table was saved successfully.","tablepress"),l.success_save_success_id_change=l.success_save+" "+(0,e.__)("The table ID was changed.","tablepress"),l.success_save_error_id_change=l.success_save+" "+(0,e.__)("The table ID could not be changed, probably because the new ID is already in use!","tablepress"),"success_save_error_id_change"===t.message&&t.error_details){const s=(0,e.__)("These errors were encountered:","tablepress");l.success_save_error_id_change+=`</p><p>${s}</p><pre>${t.error_details}</pre><p>`}const a=t.message.includes("error")?"error":"success";tp.callbacks.save_changes.after_saving_notice(a,l[t.message])},tp.callbacks.save_changes.error=function(t){t=(0,e.__)("Attention: Unfortunately, an error occurred.","tablepress")+" "+t,tp.callbacks.save_changes.after_saving_notice("error",t)},tp.callbacks.save_changes.after_saving_notice=function(e,t){const s=`save-changes-${Date.now()}`;o("#spinner-save-changes").parentNode.insertAdjacentHTML("afterend",`<div id="${s}" class="ajax-alert notice notice-${e}"><p>${t}</p></div>`);const l=o(`#${s}`);l.offsetWidth,l.style.opacity=0,l.addEventListener("transitionend",(()=>l.remove()))},tp.callbacks.screen_options={},tp.callbacks.screen_options.update=function(e){if(e.target)return"table_editor_line_clamp"===e.target.id?(tp.editor.el.style.setProperty("--table-editor-line-clamp",parseInt(e.target.value,10)),void tp.editor.updateCornerPosition()):"table_editor_column_width"===e.target.id?(tp.screen_options.table_editor_column_width=parseInt(e.target.value,10),tp.screen_options.table_editor_column_width=Math.max(tp.screen_options.table_editor_column_width,30),tp.screen_options.table_editor_column_width=Math.min(tp.screen_options.table_editor_column_width,9999),tp.editor.colgroup.forEach((e=>e.setAttribute("width",tp.screen_options.table_editor_column_width))),void tp.editor.updateCornerPosition()):void 0},tp.callbacks.screen_options.set_was_changed=function(e){e.target&&(e.target.was_changed=!0)},tp.callbacks.screen_options.save=function(t){if(!t.target)return;if(!t.target.was_changed)return;t.target.was_changed=!1;const l={action:"tablepress_save_screen_options",_ajax_nonce:tp.nonces.screen_options,tablepress:{[t.target.id]:parseInt(t.target.value,10)}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-save-changes" class="spinner-save-changes spinner is-active" title="${(0,e.__)("Changes are being saved …","tablepress")}"/>`),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(l)}).finally((()=>{o("#spinner-save-changes").remove(),document.body.classList.remove("wait")}))},tp.callbacks.table_id=tp.callbacks.table_id||{},tp.callbacks.table_id.sanitize=function(){this.value=this.value.replace(/[^0-9a-zA-Z-_]/g,"")},tp.callbacks.table_id.change=function(){if(""===this.value||"0"===this.value)return window.alert((0,e.__)("This table ID is invalid. Please enter a different table ID.","tablepress")),this.value=tp.table.new_id,this.focus(),void this.select();if(!window.confirm((0,e.__)("Do you really want to change the Table ID? All blocks and Shortcodes for this table in your posts and pages will have to be adjusted!","tablepress")))return void(this.value=tp.table.new_id);tp.table.new_id=this.value;const t=o("#table-information-shortcode");t&&(t.value=`[${tp.table.shortcode} id=${tp.table.new_id} /]`,t.focus(),t.select()),tp.helpers.unsaved_changes.set()},tp.callbacks.insert_duplicate=function(e,t,s="before"){const o="rows"===t,l=o?tp.editor.insertRow:tp.editor.insertColumn,a=o?tp.editor.getRowData:tp.editor.getColumnData,n="duplicate"===e;tp.editor.options[o?"oninsertrow":"oninsertcolumn"]=tp.callbacks.editor.oninsertroc.bind(null,t,e),tp.helpers.selection[t].forEach((function(e,t){const o=e+t,i=n?a(o):1;l(i,o,"before"===s)})),tp.helpers.unsaved_changes.set();const i=tp.helpers.selection[t].length;i>1&&tp.editor.updateSelectionFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],o?tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]:tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]+i,o?tp.helpers.selection.rows[tp.helpers.selection.rows.length-1]+i:tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.callbacks.remove=function(e){const t="rows"===e,s=t?tp.editor.options.columns.length:tp.editor.options.data.length,o=t?tp.editor.options.data.length-1:tp.editor.options.columns.length-1;if(tp.editor.options.meta&&tp.helpers.selection[e].forEach((function(e){for(let o=0;o<s;o++){const s=t?[o,e]:[e,o];delete tp.editor.options.meta[jspreadsheet.getColumnNameFromId(s)]}})),(t?tp.editor.deleteRow:tp.editor.deleteColumn)(tp.helpers.selection[e][0],tp.helpers.selection[e].length),tp.helpers.unsaved_changes.set(),o===tp.helpers.selection[e][tp.helpers.selection[e].length-1]){const e=t?tp.helpers.selection.columns[0]:tp.helpers.selection.columns[0]-1,s=t?tp.helpers.selection.rows[0]-1:tp.helpers.selection.rows[0];tp.editor.updateSelectionFromCoords(e,s,e,s)}},tp.callbacks.append=function(e,t){const s="rows"===e,o=s?tp.editor.insertRow:tp.editor.insertColumn;tp.editor.options[s?"oninsertrow":"oninsertcolumn"]=tp.callbacks.editor.oninsertroc.bind(null,e,"append"),o(t),tp.helpers.unsaved_changes.set()},tp.callbacks.move=function(e,t){const s="rows"===t;let o=tp.helpers.selection[t],l=-1;if("down"===e||"right"===e)o=o.slice().reverse(),l=1;else if("top"===e||"first"===e)l=-o[0];else if("bottom"===e||"last"===e){o=o.slice().reverse();const e="rows"===t?tp.editor.options.data.length-1:tp.editor.options.columns.length-1;l=e-o[0]}if(0===l)return;const a=s?tp.editor.moveRow:tp.editor.moveColumn;o.forEach((e=>a(e,e+l))),tp.helpers.unsaved_changes.set(),tp.editor.updateSelectionFromCoords(s?tp.helpers.selection.columns[0]:tp.helpers.selection.columns[0]+l,s?tp.helpers.selection.rows[0]+l:tp.helpers.selection.rows[0],s?tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]:tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]+l,s?tp.helpers.selection.rows[tp.helpers.selection.rows.length-1]+l:tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.callbacks.sort=function(e){tp.editor.orderBy(tp.helpers.selection.columns[0],"desc"===e)},tp.callbacks.hide_unhide=function(e,t){const s="rows"===t,o=s?"row_hidden":"column_hidden",l=s?tp.editor.options.columns.length:tp.editor.options.data.length,a="hide"===e,n={};tp.helpers.selection[t].forEach((function(e){for(let t=0;t<l;t++){const l=s?[t,e]:[e,t],i=jspreadsheet.getColumnNameFromId(l);n[i]={},n[i][o]=a}})),tp.editor.setMeta(n),tp.helpers.unsaved_changes.set(),tp.editor.updateTable()},tp.callbacks.merge_cells=function(){const e=tp.helpers.selection.columns[0],t=tp.helpers.selection.rows[0],s=tp.helpers.selection.columns.length,o=tp.helpers.selection.rows.length;for(let s=1;s<o;s++)tp.editor.setValueFromCoords(e,t+s,"#rowspan#");for(let o=1;o<s;o++)tp.editor.setValueFromCoords(e+o,t,"#colspan#");for(let l=1;l<o;l++)for(let o=1;o<s;o++)tp.editor.setValueFromCoords(e+o,t+l,"#span#");tp.helpers.unsaved_changes.set()},tp.callbacks.keyboard_shortcuts=function(e){let t="",s="",l="";if((e.ctrlKey||e.metaKey)&&(80===e.keyCode?t="show-preview":83===e.keyCode?t="save-changes":76===e.keyCode?t="insert_link":73===e.keyCode?t="insert_image":69===e.keyCode?t="advanced_editor":e.shiftKey&&e.altKey&&38===e.keyCode?(t="move",s="top",l="rows"):e.shiftKey&&e.altKey&&40===e.keyCode?(t="move",s="bottom",l="rows"):e.shiftKey&&e.altKey&&37===e.keyCode?(t="move",s="first",l="columns"):e.shiftKey&&e.altKey&&39===e.keyCode?(t="move",s="last",l="columns"):e.shiftKey&&38===e.keyCode?(t="move",s="up",l="rows"):e.shiftKey&&40===e.keyCode?(t="move",s="down",l="rows"):e.shiftKey&&37===e.keyCode?(t="move",s="left",l="columns"):e.shiftKey&&39===e.keyCode&&(t="move",s="right",l="columns")),"save-changes"===t||"show-preview"===t)document.activeElement.blur(),document.querySelector(`#tablepress_edit-buttons-2-submit .button-${t}`).click(),e.preventDefault();else if("insert_link"===t||"insert_image"===t||"advanced_editor"===t){if(o("#table-editor").contains(document.activeElement)){const e="TEXTAREA"===document.activeElement.tagName?document.activeElement:null;tp.callbacks[t].open_dialog(e)}e.preventDefault()}else"move"===t&&(o("#table-editor").contains(document.activeElement)&&"TEXTAREA"!==document.activeElement.tagName&&tp.helpers.move_allowed(l,s)&&tp.callbacks.move(s,l),e.stopImmediatePropagation())},tp.editor=jspreadsheet(o("#table-editor"),{data:tp.table.data,meta:tp.helpers.visibility.load(),wordWrap:!0,rowDrag:!0,rowResize:!0,columnSorting:!0,columnDrag:!0,columnResize:!0,defaultColWidth:tp.screen_options.table_editor_column_width,defaultColAlign:"left",parseFormulas:!1,allowExport:!1,allowComments:!1,allowManualInsertRow:!1,allowManualInsertColumn:!1,about:!1,secureFormulas:!1,detachForUpdates:!0,onselection:tp.callbacks.editor.onselection,updateTable:tp.callbacks.editor.onupdatetable,contextMenu:t=>{const s=tp.editor.options.data.length,o=tp.editor.options.columns.length,l=tp.helpers.selection.rows.length,a=tp.helpers.selection.columns.length,n=window?.navigator?.platform?.includes("Mac"),i=n?(0,e._x)("⌘","keyboard shortcut modifier key on a Mac keyboard","tablepress"):(0,e._x)("Ctrl+","keyboard shortcut modifier key on a non-Mac keyboard","tablepress"),r=n?(0,e._x)("⌥","keyboard shortcut option key on a Mac keyboard","tablepress"):(0,e._x)("Alt+","keyboard shortcut Alt key on a non-Mac keyboard","tablepress"),c={text:""};return tp.helpers.visibility.update(),[{title:(0,e.__)("Undo","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sZ","keyboard shortcut for Undo","tablepress"),i),onclick:t.undo,disabled:-1===t.historyIndex},{title:(0,e.__)("Redo","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sY","keyboard shortcut for Redo","tablepress"),i),onclick:t.redo,disabled:t.historyIndex===t.history.length-1},{type:"divisor"},{title:(0,e.__)("Cut","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sX","keyboard shortcut for Cut","tablepress"),i),onclick(){if("TEXTAREA"===document.activeElement.tagName&&document.activeElement.selectionStart!==document.activeElement.selectionEnd){document.execCommand("copy");const e=document.activeElement.selectionStart;document.activeElement.value=document.activeElement.value.slice(0,document.activeElement.selectionStart)+document.activeElement.value.slice(document.activeElement.selectionEnd),document.activeElement.selectionEnd=e}else t.copy(!0),t.setValue(t.highlighted,"")}},{title:(0,e.__)("Copy","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sC","keyboard shortcut for Copy","tablepress"),i),onclick(){"TEXTAREA"===document.activeElement.tagName&&document.activeElement.selectionStart!==document.activeElement.selectionEnd?document.execCommand("copy"):t.copy(!0)}},{title:(0,e.__)("Paste","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sV","keyboard shortcut for Paste","tablepress"),i),onclick(){"TEXTAREA"===document.activeElement.tagName?window.navigator.clipboard.readText().then((e=>{if(e){const t=document.activeElement.selectionStart+e.length;document.activeElement.value=document.activeElement.value.slice(0,document.activeElement.selectionStart)+e+document.activeElement.value.slice(document.activeElement.selectionEnd),document.activeElement.selectionEnd=t}})):t.selectedCell&&window.navigator.clipboard.readText().then((e=>{e&&t.paste(t.selectedCell[0],t.selectedCell[1],e)}))},disabled:!window?.navigator?.clipboard?.readText,tooltip:window?.navigator?.clipboard?.readText?"":(0,e.__)("Your browser does not allow pasting via the context menu. Use the keyboard shortcut instead.","tablepress")},{type:"divisor"},{title:(0,e.__)("Insert Link","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sL","keyboard shortcut for Insert Link","tablepress"),i),onclick:tp.callbacks.insert_link.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{title:(0,e.__)("Insert Image","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sI","keyboard shortcut for Insert Image","tablepress"),i),onclick:tp.callbacks.insert_image.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{title:(0,e.__)("Advanced Editor","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sE","keyboard shortcut for Advanced Editor","tablepress"),i),onclick:tp.callbacks.advanced_editor.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{type:"divisor"},{title:(0,e.__)("Duplicate …","tablepress"),submenu:[{title:(0,e._n)("Duplicate row","Duplicate rows",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"duplicate","rows")},{title:(0,e._n)("Duplicate column","Duplicate columns",a,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"duplicate","columns")}]},{title:(0,e.__)("Insert …","tablepress"),submenu:[{title:(0,e._n)("Insert row above","Insert rows above",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","rows","before")},{title:(0,e._n)("Insert row below","Insert rows below",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","rows","after")},{title:(0,e._n)("Insert column on the left","Insert columns on the left",a,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","columns","before")},{title:(0,e._n)("Insert column on the right","Insert columns on the right",a,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","columns","after")}]},{title:(0,e.__)("Append …","tablepress"),submenu:[{title:(0,e.__)("Append row","tablepress"),onclick:tp.callbacks.append.bind(null,"rows",1)},{title:(0,e.__)("Append column","tablepress"),onclick:tp.callbacks.append.bind(null,"columns",1)}]},{title:(0,e.__)("Delete …","tablepress"),submenu:[{title:(0,e._n)("Delete row","Delete rows",l,"tablepress"),onclick:tp.callbacks.remove.bind(null,"rows"),disabled:s===l,tooltip:s===l?(0,e.__)("This option is disabled.","tablepress")+" "+(0,e.__)("You can not delete all table rows!","tablepress"):""},{title:(0,e._n)("Delete column","Delete columns",a,"tablepress"),onclick:tp.callbacks.remove.bind(null,"columns"),disabled:o===a,tooltip:o===a?(0,e.__)("This option is disabled.","tablepress")+" "+(0,e.__)("You can not delete all table columns!","tablepress"):""}]},{type:"divisor"},{title:(0,e.__)("Move …","tablepress"),submenu:[{title:(0,e._n)("Move row up","Move rows up",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧↑","keyboard shortcut for Move up","tablepress"),i),onclick:tp.callbacks.move.bind(null,"up","rows"),disabled:!tp.helpers.move_allowed("rows","up")},{title:(0,e._n)("Move row down","Move rows down",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧↓","keyboard shortcut for Move down","tablepress"),i),onclick:tp.callbacks.move.bind(null,"down","rows"),disabled:!tp.helpers.move_allowed("rows","down")},{title:(0,e._n)("Move column left","Move columns left",a,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧←","keyboard shortcut for Move left","tablepress"),i),onclick:tp.callbacks.move.bind(null,"left","columns"),disabled:!tp.helpers.move_allowed("columns","left")},{title:(0,e._n)("Move column right","Move columns right",a,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧→","keyboard shortcut for Move right","tablepress"),i),onclick:tp.callbacks.move.bind(null,"right","columns"),disabled:!tp.helpers.move_allowed("columns","right")},{type:"divisor"},{title:(0,e._n)("Move row to the top","Move rows to the top",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧↑","keyboard shortcut for Move to the top","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"top","rows"),disabled:!tp.helpers.move_allowed("rows","top")},{title:(0,e._n)("Move row to the bottom","Move rows to the bottom",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧↓","keyboard shortcut for Move to the bottom","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"bottom","rows"),disabled:!tp.helpers.move_allowed("rows","bottom")},{title:(0,e._n)("Move column to first","Move columns to first",a,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧←","keyboard shortcut for Move to first","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"first","columns"),disabled:!tp.helpers.move_allowed("columns","first")},{title:(0,e._n)("Move column to last","Move columns to last",a,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧→","keyboard shortcut for Move to last","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"last","columns"),disabled:!tp.helpers.move_allowed("columns","last")}]},{title:(0,e.__)("Sort by column …","tablepress"),submenu:[{title:(0,e.__)("Sort by column ascending","tablepress"),onclick:tp.callbacks.sort.bind(null,"asc"),disabled:1!==a,tooltip:1!==a?(0,e.__)("This option is disabled because more than one column was selected.","tablepress"):""},{title:(0,e.__)("Sort by column descending","tablepress"),onclick:tp.callbacks.sort.bind(null,"desc"),disabled:1!==a,tooltip:1!==a?(0,e.__)("This option is disabled because more than one column was selected.","tablepress"):""}]},{type:"divisor"},{title:(0,e.__)("Hide/Show …","tablepress"),submenu:[{title:(0,e._n)("Hide row","Hide rows",l,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"hide","rows"),disabled:!tp.helpers.visibility.selection_contains("rows",1),tooltip:tp.helpers.visibility.selection_contains("rows",1)?"":(0,e.__)("This option is disabled because no visible rows were selected.","tablepress")},{title:(0,e._n)("Hide column","Hide columns",a,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"hide","columns"),disabled:!tp.helpers.visibility.selection_contains("columns",1),tooltip:tp.helpers.visibility.selection_contains("columns",1)?"":(0,e.__)("This option is disabled because no visible columns were selected.","tablepress")},{title:(0,e._n)("Show row","Show rows",l,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"unhide","rows"),disabled:!tp.helpers.visibility.selection_contains("rows",0),tooltip:tp.helpers.visibility.selection_contains("rows",0)?"":(0,e.__)("This option is disabled because no hidden rows were selected.","tablepress")},{title:(0,e._n)("Show column","Show columns",a,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"unhide","columns"),disabled:!tp.helpers.visibility.selection_contains("columns",0),tooltip:tp.helpers.visibility.selection_contains("columns",0)?"":(0,e.__)("This option is disabled because no hidden columns were selected.","tablepress")}]},{type:"divisor"},{title:(0,e.__)("Combine/Merge cells","tablepress"),onclick:tp.callbacks.merge_cells,disabled:1===l&&1===a||!tp.helpers.cell_merge_allowed("no-alert"),tooltip:1===l&&1===a||!tp.helpers.cell_merge_allowed("no-alert",c)?(0,e.__)("This option is disabled.","tablepress")+" "+c.text:""}]},sorting:tp.helpers.editor.sorting,onmoverow:tp.callbacks.editor.onmove,onmovecolumn:tp.callbacks.editor.onmove,onblur:tp.helpers.editor.reselect,onload:tp.helpers.editor.reselect,onchange:tp.helpers.unsaved_changes.set,onsort:tp.callbacks.editor.onsort}),tp.helpers.options.load(),o("#tablepress-page").addEventListener("click",(e=>{e.target&&(e.target.matches(".button-show-preview")?tp.callbacks.table_preview.process(e):e.target.matches(".button-save-changes")?tp.callbacks.save_changes.process(e):e.target.matches(".button-show-help-box")&&tp.callbacks.help_box.open_dialog(e))})),o("#tablepress-manipulation-controls").addEventListener("click",(t=>{if(t.target)if(t.target.matches(".button-append")){const s=t.target.dataset.type,l=o(`#${s}-append-number`),a=parseInt(l.value,10);if(isNaN(a)||a<1||a>99999){const s="rows"===t.target.dataset.type?(0,e.__)("The value for the number of rows is invalid!","tablepress"):(0,e.__)("The value for the number of columns is invalid!","tablepress");return window.alert(s),l.focus(),void l.select()}tp.callbacks.append(s,a)}else if("button-insert-link"!==t.target.id)if("button-insert-image"!==t.target.id)if("button-advanced-editor"!==t.target.id)if(t.target.matches(".button-insert-duplicate"))tp.callbacks.insert_duplicate(t.target.dataset.action,t.target.dataset.type);else{if(t.target.matches(".button-move"))return tp.helpers.move_allowed(t.target.dataset.type,t.target.dataset.direction)?void tp.callbacks.move(t.target.dataset.direction,t.target.dataset.type):void window.alert((0,e.__)("You can not do this move, because you reached the border of the table.","tablepress"));if(t.target.matches(".button-remove")){const s="rows"===t.target.dataset.type;if((s?tp.editor.options.data.length:tp.editor.options.columns.length)===tp.helpers.selection[t.target.dataset.type].length){const t=s?(0,e.__)("You can not delete all table rows!","tablepress"):(0,e.__)("You can not delete all table columns!","tablepress");return void window.alert(t)}tp.callbacks.remove(t.target.dataset.type)}else t.target.matches(".button-merge-unmerge")?tp.helpers.cell_merge_allowed("alert")&&tp.callbacks.merge_cells():t.target.matches(".button-hide-unhide")&&tp.callbacks.hide_unhide(t.target.dataset.action,t.target.dataset.type)}else tp.callbacks.advanced_editor.open_dialog();else tp.callbacks.insert_image.open_dialog();else tp.callbacks.insert_link.open_dialog()}));const l=o("#table-id");l.addEventListener("input",tp.callbacks.table_id.sanitize),l.addEventListener("change",tp.callbacks.table_id.change);const a=o("#table-information-shortcode");a&&a.addEventListener("focus",(function(){this.select()})),jQuery("#textarea-insert-helper").on("change",tp.helpers.editor.insert_from_helper_textarea),["#table-name","#table-description"].forEach((e=>o(e).addEventListener("change",tp.helpers.unsaved_changes.set))),(0,t.applyFilters)("tablepress.optionsMetaBoxes",["#tablepress_edit-table-options","#tablepress_edit-datatables-features"]).forEach((e=>o(e).addEventListener("change",tp.helpers.options.change))),document.querySelectorAll("#tablepress-body .button-module-help").forEach((e=>e.closest(".postbox").querySelector(".handle-actions").prepend(e)));const n=o("#tablepress-screen-options");n.addEventListener("input",tp.callbacks.screen_options.update),n.addEventListener("change",tp.callbacks.screen_options.set_was_changed),n.addEventListener("focusout",tp.callbacks.screen_options.save),window.addEventListener("keydown",tp.callbacks.keyboard_shortcuts,!0);const i=window?.navigator?.platform?.includes("Mac")?(0,e._x)("⌘","keyboard shortcut modifier key on a Mac keyboard","tablepress"):(0,e._x)("Ctrl+","keyboard shortcut modifier key on a non-Mac keyboard","tablepress");document.querySelectorAll(".button[data-shortcut]").forEach((t=>{const s=(0,e.sprintf)(t.dataset.shortcut,i);t.title=(0,e.sprintf)((0,e.__)("Keyboard Shortcut: %s","tablepress"),s)})),jQuery((function(){jQuery("#wp-link").on("focus","input",(function(e){e.stopPropagation()})),jQuery("body").on("focus",".media-modal .media-frame-content input, .media-modal .media-frame-content textarea",(function(e){e.stopPropagation()}))}))}();
	$( '.button-show-preview' ).forEach( ( button ) => button.classList.add( 'disabled' ) );
		$( '.button-show-preview' ).forEach( ( button ) => button.classList.remove( 'disabled' ) );
	// Update URLs in Preview links.
	$( '.button-show-preview' ).forEach( ( button ) => {
			.replace( /item=[a-zA-Z0-9_-]+/g, `item=${ data.table_id }` )
			.replace( /&_wpnonce=[a-z0-9]+/ig, `&_wpnonce=${ data.new_preview_nonce }` );
			action = 'show-preview';
	if ( 'save-changes' === action || 'show-preview' === action ) {
	if ( event.target.matches( '.button-show-preview' ) ) {
	"version": "2.2.4",
		// If the first non-whitespace character is not a { or [, the file is not a supported JSON file.
		$data = ltrim( $data );
		if ( '{' !== $first_character && '[' !== $first_character ) {
						$style->getNumberFormat() ? $style->getNumberFormat()->getFormatCode() : \TablePress\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_GENERAL, // @phpstan-ignore-line
				// Check the host of the Import URL against a blacklist of hosts, which should not be accessible, e.g. for security considerations.
				$blocked_hosts = array(
					'169.254.169.254', // AWS Meta-data API.
				if ( in_array( $host, $blocked_hosts, true ) ) {
					return new WP_Error( 'table_import_url_host_blocked', '', $this->import_config['url'] );
			&& function_exists( 'libxml_disable_entity_loader' );
			if ( '<' === $first_character ) {
			} elseif ( '{' === $first_character || '[' === $first_character ) {
				$format = 'json';
	public const version = '2.2.4'; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
	public const db_version = 70; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
			<?php if ( tb_tp_fs()->is_free_plan() ) : ?>
			if ( tb_tp_fs()->is_free_plan() ) {
		// Perform sanity checks of posted data.
			$message = "[table &#8220;{$table_id}&#8221; not found /]<br />\n";
			$message = "[table &#8220;{$table_id}&#8221; could not be loaded /]<br />\n";
			$message = "<div>Attention: The internal data of table &#8220;{$table_id}&#8221; is corrupted!</div>";
			$message = "[table &#8220;{$table_id}&#8221; not found /]<br />\n";
			$message = "[table &#8220;{$table_id}&#8221; could not be loaded /]<br />\n";
				$output = "[table-info field &#8220;{$field}&#8221; not found in table &#8220;{$table_id}&#8221; /]<br />\n";
			// @todo - Remove this check once the garbage collector is ready to be out of beta.
			if ( true !== fs_get_optional_constant( 'WP_FS__ENABLE_GARBAGE_COLLECTOR', false ) ) {
				if ( ! isset( $user_has_install[ $user_id ] ) ) {
	$this_sdk_version = '2.6.1';
			$table_id = (string) $table_id;
			$table_id = (string) $table_id;
		foreach ( $table_post as $table_id => $post_id ) {
	"version": "2.2.4",
			"version": "2.2.4",
	"version": "2.2.4",
Tags: table,spreadsheet,data,csv,excel,html,tables
Stable tag: 2.2.4
= Version 2.2.1 (November 2, 2023)=
= Version 2.2 (November 2, 2023)=
= 2.2.4 =
This update is a stability and maintenance release. Updating is highly recommended.
 * @version 2.2.4
 * Version: 2.2.4
 * Copyright 2012-2023 Tobias Bäthge
			array( '123.5', '123.5', 'Float', '123.5' ),
		$mysqli = ( isset( $GLOBALS['wpdb']->use_mysqli, $GLOBALS['wpdb']->dbh ) && $GLOBALS['wpdb']->use_mysqli );
			<br />&middot; mysqli Extension: <?php echo $mysqli ? 'true' : 'false'; ?>
			<br />&middot; mySQL (Server): <?php echo $mysqli ? mysqli_get_server_info( $GLOBALS['wpdb']->dbh ) : '<em>no mysqli</em>'; // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info ?>
			<br />&middot; mySQL (Client): <?php echo $mysqli ? mysqli_get_client_info() : '<em>no mysqli</em>'; // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_client_info ?>
			<br />&middot; ZIP support: <?php echo $data['zip_support_available'] ? 'yes' : 'no'; ?>
			<br />&middot; UTF-8 conversion: <?php echo ( function_exists( 'mb_detect_encoding' ) && function_exists( 'iconv' ) ) ? 'yes' : 'no'; ?>
		if ( tb_tp_fs()->is_free_plan() ) {
		if ( tb_tp_fs()->is_free_plan() ) :
			echo '<a href="' . $preview_url . '" class="button button-large button-show-preview" target="_blank" data-shortcut="' . esc_attr( _x( '%1$sP', 'keyboard shortcut for Preview', 'tablepress' ) ) . '">' . __( 'Preview', 'tablepress' ) . '</a>';
			echo '<a href="' . TablePress::url( array( 'action' => 'copy_table', 'item' => $data['table']['id'], 'return' => 'edit' ), true, 'admin-post.php' ) . '" class="button">' . __( 'Copy Table', 'tablepress' ) . '</a> ';
			echo '<a href="' . TablePress::url( array( 'action' => 'export', 'table_id' => $data['table']['id'] ) ) . '" class="button">' . __( 'Export Table', 'tablepress' ) . '</a> ';
			echo '<a href="' . TablePress::url( array( 'action' => 'delete_table', 'item' => $data['table']['id'], 'return' => 'edit', 'return_item' => $data['table']['id'] ), true, 'admin-post.php' ) . '" class="button delete-link">' . __( 'Delete Table', 'tablepress' ) . '</a>';
<form method="get" action="">
<form method="get" action="">
Fixed code: /.wordpress-org/ export-ignore
/.phpunit.result.cache export-ignore
/.typos.toml export-ignore
/package.json export-ignore
/rector.php export-ignore
name: Deploy to wordpress.org Repository

on:
  # Deploy to wordpress.org when a production release is created.
  release:
    types: [ released ]
  # Do a "dry run" (without comming to SVN) when the workflow is manually triggered.
  workflow_dispatch:

jobs:

  deploy_to_wordpress_org:
    name: Deploy to wordpress.org${{ github.event_name == 'workflow_dispatch' && ' (dry run)' || '' }}
    if: github.repository == 'TablePress/TablePress'
    runs-on: ubuntu-latest

    steps:
      - name: Checkout TablePress repository
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

      - name: WordPress Plugin Deploy
        id: deploy
        uses: 10up/action-wordpress-plugin-deploy@stable
        with:
          generate-zip: true
          dry-run: ${{ github.event_name == 'workflow_dispatch' }}
        env:
          SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
          SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
          SLUG: ${{ vars.SLUG }}

      - name: Get plugin version
        id: get-version
        if: ${{ github.event_name != 'workflow_dispatch' }}
        run: |
          echo "version=$(awk '/Stable tag: /{print $NF}' readme.txt)" >> $GITHUB_OUTPUT

      - name: Upload release ZIP file
        uses: actions/upload-release-asset@v1
        if: ${{ github.event_name != 'workflow_dispatch' }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ github.event.release.upload_url }}
          asset_path: ${{ steps.deploy.outputs.zip-path }}
          asset_name: ${{ vars.SLUG }}.${{ steps.get-version.outputs.version }}.zip
          asset_content_type: application/zip
<?php return array('dependencies' => array('wp-hooks', 'wp-i18n', 'wp-url'), 'version' => 'aabe698a026e2cdb0743');
!function(){"use strict";var e=window.wp.i18n,t=window.wp.hooks,s=window.wp.url;const o=e=>"#"===e[0]?document.getElementById(e.slice(1)):document.querySelectorAll(e);window.tp=window.tp||{},tp.made_changes=!1,tp.helpers=tp.helpers||{},tp.callbacks=tp.callbacks||{},tp.helpers.selection=tp.helpers.selection||{rows:[0],columns:[0]},tp.helpers.unsaved_changes=tp.helpers.unsaved_changes||{},tp.helpers.unsaved_changes.unload_dialog=function(e){e.preventDefault(),e.returnValue=""},tp.helpers.unsaved_changes.set=function(){tp.made_changes||(tp.made_changes=!0,window.addEventListener("beforeunload",tp.helpers.unsaved_changes.unload_dialog))},tp.helpers.unsaved_changes.unset=function(){tp.made_changes=!1,window.removeEventListener("beforeunload",tp.helpers.unsaved_changes.unload_dialog)},tp.helpers.options=tp.helpers.options||{},tp.helpers.options.load=function(){Object.keys(tp.table.options).forEach((function(e){if("last_editor"===e)return;if(""===(e=(0,t.applyFilters)("tablepress.optionsLoad",e)))return;let s=o(`#option-${e}`);s||(s=o(`#option-${e}-${tp.table.options[e]}`)),s&&(s instanceof HTMLInputElement&&"checkbox"===s.type?s.checked=tp.table.options[e]:s instanceof HTMLInputElement&&"radio"===s.type?s.checked=!0:s.value=tp.table.options[e])})),tp.table.options.use_datatables&&tp.helpers.editor.has_merged_cells()&&(tp.table.options.use_datatables=!1,o("#option-use_datatables").checked=!1),tp.helpers.options.check_dependencies()},tp.helpers.options.change=function(s){if(!s.target)return;const l=s.target.name||"";if(""===l)return;const n=s.target instanceof HTMLInputElement&&"checkbox"===s.target.type?"checked":"value";tp.table.options[l]=s.target[n],s.target instanceof HTMLInputElement&&"number"===s.target.type&&(tp.table.options[l]=parseInt(tp.table.options[l],10)),"use_datatables"===l&&tp.table.options.use_datatables&&tp.helpers.editor.has_merged_cells()&&(tp.table.options.use_datatables=!1,o("#option-use_datatables").checked=!1,window.alert((0,e.__)("You can not enable the Table Features for Site Visitors, because your table contains combined/merged cells.","tablepress"))),(0,t.doAction)("tablepress.optionsChange",l,n,s),tp.helpers.options.check_dependencies(),tp.helpers.unsaved_changes.set(),tp.editor.updateTable()},tp.helpers.options.check_dependencies=function(){o("#option-use_datatables").disabled=!tp.table.options.table_head,o("#notice-datatables-head-row").style.display=tp.table.options.table_head?"none":"block",o("#option-print_name_position").disabled=!tp.table.options.print_name,o("#option-print_description_position").disabled=!tp.table.options.print_description;const e=tp.table.options.use_datatables&&tp.table.options.table_head;o("#tablepress_edit-datatables-features").querySelectorAll(":scope input:not(#option-use_datatables), :scope textarea").forEach((t=>t.disabled=!e));const s=e&&tp.table.options.datatables_paginate;o("#option-datatables_lengthchange").disabled=!s,o("#option-datatables_paginate_entries").disabled=!s,(0,t.doAction)("tablepress.optionsCheckDependencies")},tp.helpers.options.validate_fields=function(){if(tp.table.options.datatables_paginate&&(isNaN(tp.table.options.datatables_paginate_entries)||tp.table.options.datatables_paginate_entries<1||tp.table.options.datatables_paginate_entries>9999)){window.alert((0,e.sprintf)((0,e.__)("The entered value in the “%1$s” field is invalid.","tablepress"),(0,e.__)("Pagination Entries","tablepress")));const t=o("#option-datatables_paginate_entries");return t.focus(),t.select(),!1}if(/[^A-Za-z0-9- _:]/.test(tp.table.options.extra_css_classes)){window.alert((0,e.sprintf)((0,e.__)("The entered value in the “%1$s” field is invalid.","tablepress"),(0,e.__)("Extra CSS Classes","tablepress")));const t=o("#option-extra_css_classes");return t.focus(),t.select(),!1}return(0,t.applyFilters)("tablepress.optionsValidateFields",!0)},tp.helpers.visibility=tp.helpers.visibility||{},tp.helpers.visibility.load=function(){const e=tp.table.visibility.rows.length,t=tp.table.visibility.columns.length,s={};for(let o=0;o<e;o++)if(1!==tp.table.visibility.rows[o])for(let e=0;e<t;e++){const t=jspreadsheet.getColumnNameFromId([e,o]);s[t]=s[t]||{},s[t].row_hidden=!0}for(let o=0;o<t;o++)if(1!==tp.table.visibility.columns[o])for(let t=0;t<e;t++){const e=jspreadsheet.getColumnNameFromId([o,t]);s[e]=s[e]||{},s[e].column_hidden=!0}return s},tp.helpers.visibility.update=function(){tp.table.visibility.rows=[];for(let e=0;e<tp.editor.options.data.length;e++)tp.table.visibility.rows[e]=1;tp.table.visibility.columns=[];for(let e=0;e<tp.editor.options.columns.length;e++)tp.table.visibility.columns[e]=1;Object.keys(tp.editor.options.meta).forEach((function(e){const t=jspreadsheet.getIdFromColumnName(e,!0);1===tp.table.visibility.rows[t[1]]&&tp.editor.options.meta[e].row_hidden&&(tp.table.visibility.rows[t[1]]=0),1===tp.table.visibility.columns[t[0]]&&tp.editor.options.meta[e].column_hidden&&(tp.table.visibility.columns[t[0]]=0)}))},tp.helpers.visibility.selection_contains=function(e,t){return tp.helpers.selection[e].some((s=>tp.table.visibility[e][s]===t))},tp.helpers.move_allowed=function(e,t){let s=tp.helpers.selection[e][0],o=0;return"down"!==t&&"right"!==t&&"bottom"!==t&&"last"!==t||(s=tp.helpers.selection[e][tp.helpers.selection[e].length-1],o="rows"===e?tp.editor.options.data.length-1:tp.editor.options.columns.length-1),o!==s},tp.helpers.cell_merge_allowed=function(t,s={}){const o="alert"===t;if(tp.table.options.table_head&&tp.table.options.use_datatables)return s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Enable Visitor Features","tablepress"),(0,e.__)("Table Features for Site Visitors","tablepress"))+" "+(0,e.__)("The Table Features for Site Visitors are not compatible with merged cells.","tablepress"),o&&window.alert(s.text),!1;const l=tp.helpers.selection.rows[0],n=tp.helpers.selection.rows[tp.helpers.selection.rows.length-1];if(tp.table.options.table_head&&0===l&&n>0)return s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Table Head Row","tablepress"),(0,e.__)("Table Options","tablepress")),o&&window.alert(s.text),!1;const a=tp.editor.options.data.length-1;return!(tp.table.options.table_foot&&a===n&&l<a&&(s.text=(0,e.sprintf)((0,e.__)("You can not combine these cells, because the “%1$s” checkbox in the “%2$s” section is checked.","tablepress"),(0,e.__)("Table Foot Row","tablepress"),(0,e.__)("Table Options","tablepress")),o&&window.alert(s.text),1))},tp.helpers.editor=tp.helpers.editor||{},tp.helpers.editor.reselect=function(e,t){void 0===t&&(t=tp.editor),t.updateSelectionFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],tp.helpers.selection.columns[tp.helpers.selection.columns.length-1],tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.helpers.editor.has_merged_cells=function(){const e=tp.editor.options.data.length,t=tp.editor.options.columns.length;for(let s=1;s<e;s++)for(let e=1;e<t;e++)if("#rowspan#"===tp.editor.options.data[s][e]||"#colspan#"===tp.editor.options.data[s][e])return!0;return!1},tp.helpers.editor.sorting=function(e){return e=e?-1:1,function(t,s){return e*((e,t)=>{const s=/(^([+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|^0x[\da-fA-F]+$|\d+)/g,o=/^\s+|\s+$/g,l=/\s+/g,n=/^0x[0-9a-f]+$/i,a=/^0/,i=e.replace(o,"")||"",r=t.replace(o,"")||"",c=i.replace(s,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0"),p=r.replace(s,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0"),d=parseInt(i.match(n),16)||1!==c.length&&Date.parse(i),b=parseInt(r.match(n),16)||d&&r.match(/(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/)&&Date.parse(r)||null,u=(e,t)=>(!e.match(a)||1===t)&&parseFloat(e)||e.replace(l," ").replace(o,"")||0;if(b){if(d<b)return-1;if(d>b)return 1}for(let e=0,t=c.length,s=p.length,o=Math.max(t,s);e<o;e++){const o=u(c[e]||"",t),l=u(p[e]||"",s);if(isNaN(o)!==isNaN(l))return isNaN(o)?1:-1;if(/[^\x00-\x80]/.test(o+l)&&o.localeCompare){const e=o.localeCompare(l);return e/Math.abs(e)}if(o<l)return-1;if(o>l)return 1}return 0})(t[1],s[1])}},tp.callbacks.editor=tp.callbacks.editor||{},tp.callbacks.editor.onselection=function(e,t,s,o,l){tp.helpers.selection={rows:[],columns:[]};for(let e=s;e<=l;e++)tp.helpers.selection.rows.push(e);for(let e=t;e<=o;e++)tp.helpers.selection.columns.push(e)},tp.callbacks.editor.onupdatetable=function(e,t,s,o,l,n,a){const i=e.jspreadsheet.options.meta[a];if(t.classList.toggle("column-hidden",Boolean(i?.column_hidden)),0===s&&(t.parentNode.classList.toggle("row-hidden",Boolean(i?.row_hidden)),t.parentNode.classList.remove("head-row","foot-row"),o===e.jspreadsheet.rows.length-1)){const t=e.jspreadsheet.content.querySelectorAll(":scope tbody tr:not(.row-hidden)");1<t.length&&(tp.table.options.table_head&&t[0].classList.add("head-row"),tp.table.options.table_foot&&t[t.length-1].classList.add("foot-row"))}},tp.callbacks.editor.oninsertroc=function(e,t,s,o,l,n,a){const i="rows"===e,r=i?"column_hidden":"row_hidden",c="duplicate"===t,p=o+(a?l:0),d=i?tp.editor.options.columns.length:tp.editor.options.data.length,b={};for(let e=0;e<d;e++){const t=i?[e,p]:[p,e],s=tp.editor.options.meta[jspreadsheet.getColumnNameFromId(t)];s&&(c?b[e]=s:s[r]&&(b[e]=b[e]||{},b[e][r]=!0))}const u=Object.keys(b);if(!u.length)return;const h={};a||o++;for(let e=0;e<l;e++){const t=o+e;u.forEach((function(e){const s=i?[e,t]:[t,e];h[jspreadsheet.getColumnNameFromId(s)]=b[e]}))}tp.editor.setMeta(h),tp.editor.updateTable()},tp.callbacks.editor.onmove=function(){tp.helpers.editor.reselect(),tp.helpers.unsaved_changes.set()},tp.callbacks.editor.onsort=function(){tp.editor.updateTable(),tp.helpers.unsaved_changes.set()},tp.helpers.editor.insert_from_helper_textarea=function(){tp.editor.setValueFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],this.value)},tp.callbacks.insert_link={},tp.callbacks.insert_link.open_dialog=function(t=null){const s=o("#textarea-insert-helper");s.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]],t?(s.selectionStart=t.selectionStart,s.selectionEnd=t.selectionEnd):(s.selectionStart=s.value.length,s.selectionEnd=s.value.length);const l=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]);o("#link-modal-title").textContent=(0,e.sprintf)((0,e.__)("Insert Link into cell %1$s","tablepress"),l),wpLink.open("textarea-insert-helper"),jexcel.current=null},tp.callbacks.insert_image={},tp.callbacks.insert_image.open_dialog=function(t=null){const s=o("#textarea-insert-helper");s.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]],t?(s.selectionStart=t.selectionStart,s.selectionEnd=t.selectionEnd):(s.selectionStart=s.value.length,s.selectionEnd=s.value.length),wp.media.editor.open("textarea-insert-helper",{frame:"post",state:"insert",title:wp.media.view.l10n.addMedia,multiple:!0});const l=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]);document.querySelector("#media-frame-title h1").textContent=(0,e.sprintf)((0,e.__)("Add media to cell %1$s","tablepress"),l),jexcel.current=null},tp.callbacks.advanced_editor={},tp.callbacks.advanced_editor.$textarea=o("#advanced-editor-content"),tp.callbacks.advanced_editor.open_dialog=function(t=null){tp.callbacks.advanced_editor.$textarea.value=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]];const s=jexcel.getColumnNameFromId([tp.helpers.selection.columns[0],tp.helpers.selection.rows[0]]),l=(0,e.sprintf)((0,e.__)("Advanced Editor for cell %1$s","tablepress"),s);o("#advanced-editor-label").textContent=l,o("#link-modal-title").textContent=(0,e.sprintf)((0,e.__)("Insert Link into cell %1$s","tablepress"),s),jQuery("#advanced-editor").wpdialog({width:600,modal:!0,title:l,resizable:!1,closeOnEscape:!0,buttons:[{text:(0,e.__)("Cancel","tablepress"),class:"button button-cancel",click(){jQuery(this).wpdialog("close")}},{text:(0,e.__)("OK","tablepress"),class:"button button-primary button-ok",click:tp.callbacks.advanced_editor.confirm_save}]}),jexcel.current=null,t?(tp.callbacks.advanced_editor.$textarea.selectionStart=t.selectionStart,tp.callbacks.advanced_editor.$textarea.selectionEnd=t.selectionEnd):(tp.callbacks.advanced_editor.$textarea.selectionStart=tp.callbacks.advanced_editor.$textarea.value.length,tp.callbacks.advanced_editor.$textarea.selectionEnd=tp.callbacks.advanced_editor.$textarea.value.length),tp.callbacks.advanced_editor.$textarea.focus()},tp.callbacks.advanced_editor.confirm_save=function(){const e=tp.editor.options.data[tp.helpers.selection.rows[0]][tp.helpers.selection.columns[0]];tp.callbacks.advanced_editor.$textarea.value!==e&&tp.editor.setValueFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],tp.callbacks.advanced_editor.$textarea.value),jQuery(this).wpdialog("close")},tp.callbacks.help_box={},tp.callbacks.help_box.open_dialog=function(t){const s=o(t.target.dataset.helpBox);jQuery(s).wpdialog({height:s.dataset.height,width:s.dataset.width,minWidth:260,modal:!0,closeOnEscape:!0,buttons:[{text:(0,e.__)("OK","tablepress"),class:"button button-ok",click(){jQuery(this).wpdialog("close")}}],open(){jQuery(this).next().find(".button-ok").trigger("focus")}})},tp.callbacks.table_preview={},tp.callbacks.table_preview.process=function(t){t.preventDefault();let l=o("#table-name").value;if(""===l.trim()&&(l=(0,e.__)("(no name)","tablepress")),tp.callbacks.table_preview.$dialog=jQuery("#table-preview").wpdialog({autoOpen:!1,width:window.innerWidth-80,height:window.innerHeight-80,modal:!0,title:(0,e.sprintf)((0,e.__)("Preview of table “%1$s” (ID %2$s)","tablepress"),l,tp.table.id),closeOnEscape:!0,buttons:[{text:(0,e.__)("OK","tablepress"),class:"button button-ok",click(){jQuery(this).wpdialog("close")}}]}),!tp.made_changes){const e=o("#table-preview-iframe");return e.src=t.target.href,e.removeAttribute("srcdoc"),void tp.callbacks.table_preview.$dialog.wpdialog("open")}tp.helpers.visibility.update();const n={action:"tablepress_preview_table",_ajax_nonce:tp.nonces.preview_table,tablepress:{id:tp.table.id,new_id:tp.table.new_id,name:o("#table-name").value,description:o("#table-description").value,data:JSON.stringify(tp.editor.options.data),options:JSON.stringify(tp.table.options),visibility:JSON.stringify(tp.table.visibility),number:{rows:tp.editor.options.data.length,columns:tp.editor.options.columns.length}}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-table-preview" class="spinner-table-preview spinner is-active" title="${(0,e.__)("The Table Preview is being loaded …","tablepress")}"/>`),o(".button-preview").forEach((e=>e.classList.add("disabled"))),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(n)}).then((e=>{if(!e.ok)throw new Error(`There was a problem with the server, HTTP response code ${e.status} (${e.statusText}).`);return e.json()})).then((e=>{if(null==e||"-1"===e||void 0===e.success)throw new Error("The JSON data returned from the server is unclear or incomplete.");if(!0!==e.success)throw new Error("The preview could not be loaded.");tp.callbacks.table_preview.success(e)})).catch((e=>tp.callbacks.table_preview.error(e.message))).finally((()=>{o("#spinner-table-preview").remove(),o(".button-preview").forEach((e=>e.classList.remove("disabled"))),document.body.classList.remove("wait")}))},tp.callbacks.table_preview.success=function(e){const t=o("#table-preview-iframe");t.src="",t.srcdoc=`<!DOCTYPE html><html><head>${e.head_html}</head><body>${e.body_html}</body></html>`,tp.callbacks.table_preview.$dialog.wpdialog("open")},tp.callbacks.table_preview.error=function(t){t=(0,e.__)("Attention: Unfortunately, an error occurred.","tablepress")+" "+t;const s=`show-preview-${Date.now()}`;o("#spinner-table-preview").parentNode.insertAdjacentHTML("afterend",`<div id="${s}" class="ajax-alert notice notice-error"><p>${t}</p></div>`);const l=o(`#${s}`);l.offsetWidth,l.style.opacity=0,l.addEventListener("transitionend",(()=>l.remove()))},tp.callbacks.save_changes={},tp.callbacks.save_changes.process=function(t){if(!tp.helpers.options.validate_fields())return;tp.helpers.visibility.update();const l={action:"tablepress_save_table",_ajax_nonce:tp.nonces.edit_table,tablepress:{id:tp.table.id,new_id:tp.table.new_id,name:o("#table-name").value,description:o("#table-description").value,data:JSON.stringify(tp.editor.options.data),options:JSON.stringify(tp.table.options),visibility:JSON.stringify(tp.table.visibility),number:{rows:tp.editor.options.data.length,columns:tp.editor.options.columns.length}}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-save-changes" class="spinner-save-changes spinner is-active" title="${(0,e.__)("Changes are being saved …","tablepress")}"/>`),o(".button-save-changes").forEach((e=>e.disabled=!0)),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(l)}).then((e=>{if(!e.ok)throw new Error(`There was a problem with the server, HTTP response code ${e.status} (${e.statusText}).`);return e.json()})).then((t=>{if(null==t||"-1"===t||void 0===t.success)throw new Error("The JSON data returned from the server is unclear or incomplete.");if(!0!==t.success){const s=(0,e.__)("These errors were encountered:","tablepress"),o=t.error_details?`</p><p>${s}</p><pre>${t.error_details}</pre><p>`:"";throw new Error(`The table could not be saved to the database properly.${o}`)}tp.callbacks.save_changes.success(t)})).catch((e=>tp.callbacks.save_changes.error(e.message))).finally((()=>{o("#spinner-save-changes").remove(),o(".button-save-changes").forEach((e=>e.disabled=!1)),document.body.classList.remove("wait")}))},tp.callbacks.save_changes.success=function(t){tp.table.id!==t.table_id&&window?.history?.pushState&&window.history.pushState("","",window.location.href.replace(/table_id=[0-9a-zA-Z-_]+/gi,`table_id=${t.table_id}`)),tp.table.id=t.table_id,tp.table.new_id=t.table_id,o("#table-id").value=t.table_id;const s=o("#table-information-shortcode");s&&(s.value=`[${tp.table.shortcode} id=${t.table_id} /]`),tp.nonces.edit_table=t.new_edit_nonce,tp.nonces.preview_table=t.new_preview_nonce,tp.nonces.copy_table=t.new_copy_nonce,tp.nonces.delete_table=t.new_delete_nonce,["preview","copy","delete"].forEach((e=>{o(`.button-${e}`).forEach((s=>{s.href=s.href.replace(/item=[a-zA-Z0-9_-]+/g,`item=${t.table_id}`).replace(/&_wpnonce=[a-z0-9]+/gi,`&_wpnonce=${t[`new_${e}_nonce`]}`)}))})),o(".button-export").forEach((e=>{e.href=e.href.replace(/table_id=[a-zA-Z0-9_-]+/g,`table_id=${t.table_id}`)})),o("#last-modified").textContent=t.last_modified,o("#last-editor").textContent=t.last_editor,tp.helpers.unsaved_changes.unset();const l={};if(l.success_save=(0,e.__)("The table was saved successfully.","tablepress"),l.success_save_success_id_change=l.success_save+" "+(0,e.__)("The table ID was changed.","tablepress"),l.success_save_error_id_change=l.success_save+" "+(0,e.__)("The table ID could not be changed, probably because the new ID is already in use!","tablepress"),"success_save_error_id_change"===t.message&&t.error_details){const s=(0,e.__)("These errors were encountered:","tablepress");l.success_save_error_id_change+=`</p><p>${s}</p><pre>${t.error_details}</pre><p>`}const n=t.message.includes("error")?"error":"success";tp.callbacks.save_changes.after_saving_notice(n,l[t.message])},tp.callbacks.save_changes.error=function(t){t=(0,e.__)("Attention: Unfortunately, an error occurred.","tablepress")+" "+t,tp.callbacks.save_changes.after_saving_notice("error",t)},tp.callbacks.save_changes.after_saving_notice=function(e,t){const s=`save-changes-${Date.now()}`;o("#spinner-save-changes").parentNode.insertAdjacentHTML("afterend",`<div id="${s}" class="ajax-alert notice notice-${e}"><p>${t}</p></div>`);const l=o(`#${s}`);l.offsetWidth,l.style.opacity=0,l.addEventListener("transitionend",(()=>l.remove()))},tp.callbacks.screen_options={},tp.callbacks.screen_options.update=function(e){if(e.target)return"table_editor_line_clamp"===e.target.id?(tp.editor.el.style.setProperty("--table-editor-line-clamp",parseInt(e.target.value,10)),void tp.editor.updateCornerPosition()):"table_editor_column_width"===e.target.id?(tp.screen_options.table_editor_column_width=parseInt(e.target.value,10),tp.screen_options.table_editor_column_width=Math.max(tp.screen_options.table_editor_column_width,30),tp.screen_options.table_editor_column_width=Math.min(tp.screen_options.table_editor_column_width,9999),tp.editor.colgroup.forEach((e=>e.setAttribute("width",tp.screen_options.table_editor_column_width))),void tp.editor.updateCornerPosition()):void 0},tp.callbacks.screen_options.set_was_changed=function(e){e.target&&(e.target.was_changed=!0)},tp.callbacks.screen_options.save=function(t){if(!t.target)return;if(!t.target.was_changed)return;t.target.was_changed=!1;const l={action:"tablepress_save_screen_options",_ajax_nonce:tp.nonces.screen_options,tablepress:{[t.target.id]:parseInt(t.target.value,10)}};t.target.parentNode.insertAdjacentHTML("beforeend",`<span id="spinner-save-changes" class="spinner-save-changes spinner is-active" title="${(0,e.__)("Changes are being saved …","tablepress")}"/>`),document.body.classList.add("wait"),fetch(ajaxurl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:(0,s.buildQueryString)(l)}).finally((()=>{o("#spinner-save-changes").remove(),document.body.classList.remove("wait")}))},tp.callbacks.table_id=tp.callbacks.table_id||{},tp.callbacks.table_id.sanitize=function(){this.value=this.value.replace(/[^0-9a-zA-Z-_]/g,"")},tp.callbacks.table_id.change=function(){if(""===this.value||"0"===this.value)return window.alert((0,e.__)("This table ID is invalid. Please enter a different table ID.","tablepress")),this.value=tp.table.new_id,this.focus(),void this.select();if(!window.confirm((0,e.__)("Do you really want to change the Table ID? All blocks and Shortcodes for this table in your posts and pages will have to be adjusted!","tablepress")))return void(this.value=tp.table.new_id);tp.table.new_id=this.value;const t=o("#table-information-shortcode");t&&(t.value=`[${tp.table.shortcode} id=${tp.table.new_id} /]`,t.focus(),t.select()),tp.helpers.unsaved_changes.set()},tp.callbacks.insert_duplicate=function(e,t,s="before"){const o="rows"===t,l=o?tp.editor.insertRow:tp.editor.insertColumn,n=o?tp.editor.getRowData:tp.editor.getColumnData,a="duplicate"===e;tp.editor.options[o?"oninsertrow":"oninsertcolumn"]=tp.callbacks.editor.oninsertroc.bind(null,t,e),tp.helpers.selection[t].forEach((function(e,t){const o=e+t,i=a?n(o):1;l(i,o,"before"===s)})),tp.helpers.unsaved_changes.set();const i=tp.helpers.selection[t].length;i>1&&tp.editor.updateSelectionFromCoords(tp.helpers.selection.columns[0],tp.helpers.selection.rows[0],o?tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]:tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]+i,o?tp.helpers.selection.rows[tp.helpers.selection.rows.length-1]+i:tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.callbacks.remove=function(e){const t="rows"===e,s=t?tp.editor.options.columns.length:tp.editor.options.data.length,o=t?tp.editor.options.data.length-1:tp.editor.options.columns.length-1;if(tp.editor.options.meta&&tp.helpers.selection[e].forEach((function(e){for(let o=0;o<s;o++){const s=t?[o,e]:[e,o];delete tp.editor.options.meta[jspreadsheet.getColumnNameFromId(s)]}})),(t?tp.editor.deleteRow:tp.editor.deleteColumn)(tp.helpers.selection[e][0],tp.helpers.selection[e].length),tp.helpers.unsaved_changes.set(),o===tp.helpers.selection[e][tp.helpers.selection[e].length-1]){const e=t?tp.helpers.selection.columns[0]:tp.helpers.selection.columns[0]-1,s=t?tp.helpers.selection.rows[0]-1:tp.helpers.selection.rows[0];tp.editor.updateSelectionFromCoords(e,s,e,s)}},tp.callbacks.append=function(e,t){const s="rows"===e,o=s?tp.editor.insertRow:tp.editor.insertColumn;tp.editor.options[s?"oninsertrow":"oninsertcolumn"]=tp.callbacks.editor.oninsertroc.bind(null,e,"append"),o(t),tp.helpers.unsaved_changes.set()},tp.callbacks.move=function(e,t){const s="rows"===t;let o=tp.helpers.selection[t],l=-1;if("down"===e||"right"===e)o=o.slice().reverse(),l=1;else if("top"===e||"first"===e)l=-o[0];else if("bottom"===e||"last"===e){o=o.slice().reverse();const e="rows"===t?tp.editor.options.data.length-1:tp.editor.options.columns.length-1;l=e-o[0]}if(0===l)return;const n=s?tp.editor.moveRow:tp.editor.moveColumn;o.forEach((e=>n(e,e+l))),tp.helpers.unsaved_changes.set(),tp.editor.updateSelectionFromCoords(s?tp.helpers.selection.columns[0]:tp.helpers.selection.columns[0]+l,s?tp.helpers.selection.rows[0]+l:tp.helpers.selection.rows[0],s?tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]:tp.helpers.selection.columns[tp.helpers.selection.columns.length-1]+l,s?tp.helpers.selection.rows[tp.helpers.selection.rows.length-1]+l:tp.helpers.selection.rows[tp.helpers.selection.rows.length-1])},tp.callbacks.sort=function(e){tp.editor.orderBy(tp.helpers.selection.columns[0],"desc"===e)},tp.callbacks.hide_unhide=function(e,t){const s="rows"===t,o=s?"row_hidden":"column_hidden",l=s?tp.editor.options.columns.length:tp.editor.options.data.length,n="hide"===e,a={};tp.helpers.selection[t].forEach((function(e){for(let t=0;t<l;t++){const l=s?[t,e]:[e,t],i=jspreadsheet.getColumnNameFromId(l);a[i]={},a[i][o]=n}})),tp.editor.setMeta(a),tp.helpers.unsaved_changes.set(),tp.editor.updateTable()},tp.callbacks.merge_cells=function(){const e=tp.helpers.selection.columns[0],t=tp.helpers.selection.rows[0],s=tp.helpers.selection.columns.length,o=tp.helpers.selection.rows.length;for(let s=1;s<o;s++)tp.editor.setValueFromCoords(e,t+s,"#rowspan#");for(let o=1;o<s;o++)tp.editor.setValueFromCoords(e+o,t,"#colspan#");for(let l=1;l<o;l++)for(let o=1;o<s;o++)tp.editor.setValueFromCoords(e+o,t+l,"#span#");tp.helpers.unsaved_changes.set()},tp.callbacks.keyboard_shortcuts=function(e){let t="",s="",l="";if((e.ctrlKey||e.metaKey)&&(80===e.keyCode?t="preview":83===e.keyCode?t="save-changes":76===e.keyCode?t="insert_link":73===e.keyCode?t="insert_image":69===e.keyCode?t="advanced_editor":e.shiftKey&&e.altKey&&38===e.keyCode?(t="move",s="top",l="rows"):e.shiftKey&&e.altKey&&40===e.keyCode?(t="move",s="bottom",l="rows"):e.shiftKey&&e.altKey&&37===e.keyCode?(t="move",s="first",l="columns"):e.shiftKey&&e.altKey&&39===e.keyCode?(t="move",s="last",l="columns"):e.shiftKey&&38===e.keyCode?(t="move",s="up",l="rows"):e.shiftKey&&40===e.keyCode?(t="move",s="down",l="rows"):e.shiftKey&&37===e.keyCode?(t="move",s="left",l="columns"):e.shiftKey&&39===e.keyCode&&(t="move",s="right",l="columns")),"save-changes"===t||"preview"===t)document.activeElement.blur(),document.querySelector(`#tablepress_edit-buttons-2-submit .button-${t}`).click(),e.preventDefault();else if("insert_link"===t||"insert_image"===t||"advanced_editor"===t){if(o("#table-editor").contains(document.activeElement)){const e="TEXTAREA"===document.activeElement.tagName?document.activeElement:null;tp.callbacks[t].open_dialog(e)}e.preventDefault()}else"move"===t&&(o("#table-editor").contains(document.activeElement)&&"TEXTAREA"!==document.activeElement.tagName&&tp.helpers.move_allowed(l,s)&&tp.callbacks.move(s,l),e.stopImmediatePropagation())},tp.editor=jspreadsheet(o("#table-editor"),{data:tp.table.data,meta:tp.helpers.visibility.load(),wordWrap:!0,rowDrag:!0,rowResize:!0,columnSorting:!0,columnDrag:!0,columnResize:!0,defaultColWidth:tp.screen_options.table_editor_column_width,defaultColAlign:"left",parseFormulas:!1,allowExport:!1,allowComments:!1,allowManualInsertRow:!1,allowManualInsertColumn:!1,about:!1,secureFormulas:!1,detachForUpdates:!0,onselection:tp.callbacks.editor.onselection,updateTable:tp.callbacks.editor.onupdatetable,contextMenu:t=>{const s=tp.editor.options.data.length,o=tp.editor.options.columns.length,l=tp.helpers.selection.rows.length,n=tp.helpers.selection.columns.length,a=window?.navigator?.platform?.includes("Mac"),i=a?(0,e._x)("⌘","keyboard shortcut modifier key on a Mac keyboard","tablepress"):(0,e._x)("Ctrl+","keyboard shortcut modifier key on a non-Mac keyboard","tablepress"),r=a?(0,e._x)("⌥","keyboard shortcut option key on a Mac keyboard","tablepress"):(0,e._x)("Alt+","keyboard shortcut Alt key on a non-Mac keyboard","tablepress"),c={text:""};return tp.helpers.visibility.update(),[{title:(0,e.__)("Undo","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sZ","keyboard shortcut for Undo","tablepress"),i),onclick:t.undo,disabled:-1===t.historyIndex},{title:(0,e.__)("Redo","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sY","keyboard shortcut for Redo","tablepress"),i),onclick:t.redo,disabled:t.historyIndex===t.history.length-1},{type:"divisor"},{title:(0,e.__)("Cut","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sX","keyboard shortcut for Cut","tablepress"),i),onclick(){if("TEXTAREA"===document.activeElement.tagName&&document.activeElement.selectionStart!==document.activeElement.selectionEnd){document.execCommand("copy");const e=document.activeElement.selectionStart;document.activeElement.value=document.activeElement.value.slice(0,document.activeElement.selectionStart)+document.activeElement.value.slice(document.activeElement.selectionEnd),document.activeElement.selectionEnd=e}else t.copy(!0),t.setValue(t.highlighted,"")}},{title:(0,e.__)("Copy","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sC","keyboard shortcut for Copy","tablepress"),i),onclick(){"TEXTAREA"===document.activeElement.tagName&&document.activeElement.selectionStart!==document.activeElement.selectionEnd?document.execCommand("copy"):t.copy(!0)}},{title:(0,e.__)("Paste","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sV","keyboard shortcut for Paste","tablepress"),i),onclick(){"TEXTAREA"===document.activeElement.tagName?window.navigator.clipboard.readText().then((e=>{if(e){const t=document.activeElement.selectionStart+e.length;document.activeElement.value=document.activeElement.value.slice(0,document.activeElement.selectionStart)+e+document.activeElement.value.slice(document.activeElement.selectionEnd),document.activeElement.selectionEnd=t}})):t.selectedCell&&window.navigator.clipboard.readText().then((e=>{e&&t.paste(t.selectedCell[0],t.selectedCell[1],e)}))},disabled:!window?.navigator?.clipboard?.readText,tooltip:window?.navigator?.clipboard?.readText?"":(0,e.__)("Your browser does not allow pasting via the context menu. Use the keyboard shortcut instead.","tablepress")},{type:"divisor"},{title:(0,e.__)("Insert Link","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sL","keyboard shortcut for Insert Link","tablepress"),i),onclick:tp.callbacks.insert_link.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{title:(0,e.__)("Insert Image","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sI","keyboard shortcut for Insert Image","tablepress"),i),onclick:tp.callbacks.insert_image.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{title:(0,e.__)("Advanced Editor","tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$sE","keyboard shortcut for Advanced Editor","tablepress"),i),onclick:tp.callbacks.advanced_editor.open_dialog.bind(null,"TEXTAREA"===document.activeElement.tagName?document.activeElement:null)},{type:"divisor"},{title:(0,e.__)("Duplicate …","tablepress"),submenu:[{title:(0,e._n)("Duplicate row","Duplicate rows",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"duplicate","rows")},{title:(0,e._n)("Duplicate column","Duplicate columns",n,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"duplicate","columns")}]},{title:(0,e.__)("Insert …","tablepress"),submenu:[{title:(0,e._n)("Insert row above","Insert rows above",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","rows","before")},{title:(0,e._n)("Insert row below","Insert rows below",l,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","rows","after")},{title:(0,e._n)("Insert column on the left","Insert columns on the left",n,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","columns","before")},{title:(0,e._n)("Insert column on the right","Insert columns on the right",n,"tablepress"),onclick:tp.callbacks.insert_duplicate.bind(null,"insert","columns","after")}]},{title:(0,e.__)("Append …","tablepress"),submenu:[{title:(0,e.__)("Append row","tablepress"),onclick:tp.callbacks.append.bind(null,"rows",1)},{title:(0,e.__)("Append column","tablepress"),onclick:tp.callbacks.append.bind(null,"columns",1)}]},{title:(0,e.__)("Delete …","tablepress"),submenu:[{title:(0,e._n)("Delete row","Delete rows",l,"tablepress"),onclick:tp.callbacks.remove.bind(null,"rows"),disabled:s===l,tooltip:s===l?(0,e.__)("This option is disabled.","tablepress")+" "+(0,e.__)("You can not delete all table rows!","tablepress"):""},{title:(0,e._n)("Delete column","Delete columns",n,"tablepress"),onclick:tp.callbacks.remove.bind(null,"columns"),disabled:o===n,tooltip:o===n?(0,e.__)("This option is disabled.","tablepress")+" "+(0,e.__)("You can not delete all table columns!","tablepress"):""}]},{type:"divisor"},{title:(0,e.__)("Move …","tablepress"),submenu:[{title:(0,e._n)("Move row up","Move rows up",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧↑","keyboard shortcut for Move up","tablepress"),i),onclick:tp.callbacks.move.bind(null,"up","rows"),disabled:!tp.helpers.move_allowed("rows","up")},{title:(0,e._n)("Move row down","Move rows down",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧↓","keyboard shortcut for Move down","tablepress"),i),onclick:tp.callbacks.move.bind(null,"down","rows"),disabled:!tp.helpers.move_allowed("rows","down")},{title:(0,e._n)("Move column left","Move columns left",n,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧←","keyboard shortcut for Move left","tablepress"),i),onclick:tp.callbacks.move.bind(null,"left","columns"),disabled:!tp.helpers.move_allowed("columns","left")},{title:(0,e._n)("Move column right","Move columns right",n,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s⇧→","keyboard shortcut for Move right","tablepress"),i),onclick:tp.callbacks.move.bind(null,"right","columns"),disabled:!tp.helpers.move_allowed("columns","right")},{type:"divisor"},{title:(0,e._n)("Move row to the top","Move rows to the top",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧↑","keyboard shortcut for Move to the top","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"top","rows"),disabled:!tp.helpers.move_allowed("rows","top")},{title:(0,e._n)("Move row to the bottom","Move rows to the bottom",l,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧↓","keyboard shortcut for Move to the bottom","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"bottom","rows"),disabled:!tp.helpers.move_allowed("rows","bottom")},{title:(0,e._n)("Move column to first","Move columns to first",n,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧←","keyboard shortcut for Move to first","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"first","columns"),disabled:!tp.helpers.move_allowed("columns","first")},{title:(0,e._n)("Move column to last","Move columns to last",n,"tablepress"),shortcut:(0,e.sprintf)((0,e._x)("%1$s%2$s⇧→","keyboard shortcut for Move to last","tablepress"),i,r),onclick:tp.callbacks.move.bind(null,"last","columns"),disabled:!tp.helpers.move_allowed("columns","last")}]},{title:(0,e.__)("Sort by column …","tablepress"),submenu:[{title:(0,e.__)("Sort by column ascending","tablepress"),onclick:tp.callbacks.sort.bind(null,"asc"),disabled:1!==n,tooltip:1!==n?(0,e.__)("This option is disabled because more than one column was selected.","tablepress"):""},{title:(0,e.__)("Sort by column descending","tablepress"),onclick:tp.callbacks.sort.bind(null,"desc"),disabled:1!==n,tooltip:1!==n?(0,e.__)("This option is disabled because more than one column was selected.","tablepress"):""}]},{type:"divisor"},{title:(0,e.__)("Hide/Show …","tablepress"),submenu:[{title:(0,e._n)("Hide row","Hide rows",l,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"hide","rows"),disabled:!tp.helpers.visibility.selection_contains("rows",1),tooltip:tp.helpers.visibility.selection_contains("rows",1)?"":(0,e.__)("This option is disabled because no visible rows were selected.","tablepress")},{title:(0,e._n)("Hide column","Hide columns",n,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"hide","columns"),disabled:!tp.helpers.visibility.selection_contains("columns",1),tooltip:tp.helpers.visibility.selection_contains("columns",1)?"":(0,e.__)("This option is disabled because no visible columns were selected.","tablepress")},{title:(0,e._n)("Show row","Show rows",l,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"unhide","rows"),disabled:!tp.helpers.visibility.selection_contains("rows",0),tooltip:tp.helpers.visibility.selection_contains("rows",0)?"":(0,e.__)("This option is disabled because no hidden rows were selected.","tablepress")},{title:(0,e._n)("Show column","Show columns",n,"tablepress"),onclick:tp.callbacks.hide_unhide.bind(null,"unhide","columns"),disabled:!tp.helpers.visibility.selection_contains("columns",0),tooltip:tp.helpers.visibility.selection_contains("columns",0)?"":(0,e.__)("This option is disabled because no hidden columns were selected.","tablepress")}]},{type:"divisor"},{title:(0,e.__)("Combine/Merge cells","tablepress"),onclick:tp.callbacks.merge_cells,disabled:1===l&&1===n||!tp.helpers.cell_merge_allowed("no-alert"),tooltip:1===l&&1===n||!tp.helpers.cell_merge_allowed("no-alert",c)?(0,e.__)("This option is disabled.","tablepress")+" "+c.text:""}]},sorting:tp.helpers.editor.sorting,onmoverow:tp.callbacks.editor.onmove,onmovecolumn:tp.callbacks.editor.onmove,onblur:tp.helpers.editor.reselect,onload:tp.helpers.editor.reselect,onchange:tp.helpers.unsaved_changes.set,onsort:tp.callbacks.editor.onsort}),tp.helpers.options.load(),o("#tablepress-page").addEventListener("click",(e=>{e.target&&(e.target.matches(".button-preview")?tp.callbacks.table_preview.process(e):e.target.matches(".button-save-changes")?tp.callbacks.save_changes.process(e):e.target.matches(".button-show-help-box")&&tp.callbacks.help_box.open_dialog(e))})),o("#tablepress-manipulation-controls").addEventListener("click",(t=>{if(t.target)if(t.target.matches(".button-append")){const s=t.target.dataset.type,l=o(`#${s}-append-number`),n=parseInt(l.value,10);if(isNaN(n)||n<1||n>99999){const s="rows"===t.target.dataset.type?(0,e.__)("The value for the number of rows is invalid!","tablepress"):(0,e.__)("The value for the number of columns is invalid!","tablepress");return window.alert(s),l.focus(),void l.select()}tp.callbacks.append(s,n)}else if("button-insert-link"!==t.target.id)if("button-insert-image"!==t.target.id)if("button-advanced-editor"!==t.target.id)if(t.target.matches(".button-insert-duplicate"))tp.callbacks.insert_duplicate(t.target.dataset.action,t.target.dataset.type);else{if(t.target.matches(".button-move"))return tp.helpers.move_allowed(t.target.dataset.type,t.target.dataset.direction)?void tp.callbacks.move(t.target.dataset.direction,t.target.dataset.type):void window.alert((0,e.__)("You can not do this move, because you reached the border of the table.","tablepress"));if(t.target.matches(".button-remove")){const s="rows"===t.target.dataset.type;if((s?tp.editor.options.data.length:tp.editor.options.columns.length)===tp.helpers.selection[t.target.dataset.type].length){const t=s?(0,e.__)("You can not delete all table rows!","tablepress"):(0,e.__)("You can not delete all table columns!","tablepress");return void window.alert(t)}tp.callbacks.remove(t.target.dataset.type)}else t.target.matches(".button-merge-unmerge")?tp.helpers.cell_merge_allowed("alert")&&tp.callbacks.merge_cells():t.target.matches(".button-hide-unhide")&&tp.callbacks.hide_unhide(t.target.dataset.action,t.target.dataset.type)}else tp.callbacks.advanced_editor.open_dialog();else tp.callbacks.insert_image.open_dialog();else tp.callbacks.insert_link.open_dialog()}));const l=o("#table-id");l.addEventListener("input",tp.callbacks.table_id.sanitize),l.addEventListener("change",tp.callbacks.table_id.change);const n=o("#table-information-shortcode");n&&n.addEventListener("focus",(function(){this.select()})),jQuery("#textarea-insert-helper").on("change",tp.helpers.editor.insert_from_helper_textarea),["#table-name","#table-description"].forEach((e=>o(e).addEventListener("change",tp.helpers.unsaved_changes.set))),(0,t.applyFilters)("tablepress.optionsMetaBoxes",["#tablepress_edit-table-options","#tablepress_edit-datatables-features"]).forEach((e=>o(e).addEventListener("change",tp.helpers.options.change))),document.querySelectorAll("#tablepress-body .button-module-help").forEach((e=>e.closest(".postbox").querySelector(".handle-actions").prepend(e)));const a=o("#tablepress-screen-options");a.addEventListener("input",tp.callbacks.screen_options.update),a.addEventListener("change",tp.callbacks.screen_options.set_was_changed),a.addEventListener("focusout",tp.callbacks.screen_options.save),window.addEventListener("keydown",tp.callbacks.keyboard_shortcuts,!0);const i=window?.navigator?.platform?.includes("Mac")?(0,e._x)("⌘","keyboard shortcut modifier key on a Mac keyboard","tablepress"):(0,e._x)("Ctrl+","keyboard shortcut modifier key on a non-Mac keyboard","tablepress");document.querySelectorAll(".button[data-shortcut]").forEach((t=>{const s=(0,e.sprintf)(t.dataset.shortcut,i);t.title=(0,e.sprintf)((0,e.__)("Keyboard Shortcut: %s","tablepress"),s)})),jQuery((function(){jQuery("#wp-link").on("focus","input",(function(e){e.stopPropagation()})),jQuery("body").on("focus",".media-modal .media-frame-content input, .media-modal .media-frame-content textarea",(function(e){e.stopPropagation()}))}))}();
	$( '.button-preview' ).forEach( ( button ) => button.classList.add( 'disabled' ) );
		$( '.button-preview' ).forEach( ( button ) => button.classList.remove( 'disabled' ) );
	tp.nonces.copy_table = data.new_copy_nonce;
	tp.nonces.delete_table = data.new_delete_nonce;

	// Update URLs in Preview, Copy, and Delete links/buttons.
	[ 'preview', 'copy', 'delete' ].forEach( ( action ) => {
		$( `.button-${ action }` ).forEach( ( button ) => {
			button.href = button.href
				.replace( /item=[a-zA-Z0-9_-]+/g, `item=${ data.table_id }` ) // Updates both the "item" and the "return_item" parameters.
				.replace( /&_wpnonce=[a-z0-9]+/ig, `&_wpnonce=${ data[ `new_${ action }_nonce` ] }` );
		} );
	} );
	// Update URL in Export links/buttons.
	$( '.button-export' ).forEach( ( button ) => {
			.replace( /table_id=[a-zA-Z0-9_-]+/g, `table_id=${ data.table_id }` );
			action = 'preview';
	if ( 'save-changes' === action || 'preview' === action ) {
	if ( event.target.matches( '.button-preview' ) ) {
	"version": "2.2.5",
		$data = trim( $data );

		// If the file does not begin / end with [ / ] or { / }, it's not a supported JSON file.
		$last_character = $data[-1];
		if ( ! ( '[' === $first_character && ']' === $last_character ) && ! ( '{' === $first_character && '}' === $last_character ) ) {

					$format = $style->getNumberFormat()->getFormatCode() ?? \TablePress\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_GENERAL;

					// Fix floating point precision issues with numbers in the "General" Excel .xlsx format.
					if ( 'xlsx' === $detected_format && \TablePress\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_GENERAL === $format && is_numeric( $cell_data ) ) {
						$cell_data = (string) (float) $cell_data; // Type-cast strings to float and back.
					}
						$format,
				// Check the IP address of the host against a blocklist of hosts which should not be accessible, e.g. for security considerations.
				$ip = gethostbyname( $host ); // If no IP address can be found, this will return the host name, which will then be checked against the blocklist.
				$blocked_ips = array(
					'169.254.169.254', // Meta-data API for various cloud providers.
					'169.254.170.2', // AWS task metadata endpoint.
					'192.0.0.192', // Oracle Cloud endpoint.
					'100.100.100.200', // Alibaba Cloud endpoint.
				if ( in_array( $ip, $blocked_ips, true ) ) {
					return new WP_Error( 'table_import_url_host_blocked', '', array( 'url' => $this->import_config['url'], 'ip' => $ip ) );
			&& ( function_exists( 'libxml_disable_entity_loader' ) || PHP_VERSION_ID >= 80000 ); // This function is only needed for older versions of PHP.
			$data = trim( $data );
			$last_character = $data[-1];

			if ( '<' === $first_character && '>' === $last_character ) {
			} elseif ( ( '[' === $first_character && ']' === $last_character ) || ( '{' === $first_character && '}' === $last_character ) ) {
				$json_table = json_decode( $data, true );
				if ( ! is_null( $json_table ) ) {
					$format = 'json';
				}
	public const version = '2.2.5'; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
	public const db_version = 73; // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase
			<?php if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) : ?>
			if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) {
		// Perform confidence checks of posted data.
			$response['new_copy_nonce'] = wp_create_nonce( TablePress::nonce( 'copy_table', $table['id'] ) ); // @phpstan-ignore-line
			$response['new_delete_nonce'] = wp_create_nonce( TablePress::nonce( 'delete_table', $table['id'] ) ); // @phpstan-ignore-line
			$table_id = (string) $table_id; // Ensure that the table ID is a string, as it comes from an array key where numeric strings are converted to integers.

			$message = "&#91;table “{$table_id}” not found /&#93;<br />\n";
			$message = "&#91;table “{$table_id}” could not be loaded /&#93;<br />\n";
			$message = "<div>Attention: The internal data of table “{$table_id}” is corrupted!</div>";
			$message = "&#91;table “{$table_id}” not found /&#93;<br />\n";
			$message = "&#91;table “{$table_id}” could not be loaded /&#93;<br />\n";
				$output = "&#91;table-info field “{$field}” not found in table “{$table_id}” /&#93;<br />\n";
			if ( true !== fs_get_optional_constant( 'WP_FS__ENABLE_GARBAGE_COLLECTOR', true ) ) {
				if ( ! isset( $user_has_install_map[ $user_id ] ) ) {
	$this_sdk_version = '2.6.2';
			$table_id = (string) $table_id; // Ensure that the table ID is a string, as it comes from an array key where numeric strings are converted to integers.


			$table_id = (string) $table_id; // Ensure that the table ID is a string, as it comes from an array key where numeric strings are converted to integers.


		foreach ( $table_post as $post_id ) {
			$table_id = (string) $table_id; // Ensure that the table ID is a string, as it comes from an array key where numeric strings are converted to integers.
	"version": "2.2.5",
			"version": "2.2.5",
	"version": "2.2.5",
	dynamicConstantNames:
		- TABLEPRESS_IS_PLAYGROUND_PREVIEW
Beginner-friendly step-by-step [tutorials, guides, and how-tos](https://tablepress.org/tutorials/) show how to achieve common and popular tasks with TablePress.
Tags: table, spreadsheet, csv, excel, tables
Stable tag: 2.2.5
Beginner-friendly step-by-step [tutorials, guides, and how-tos](https://tablepress.org/tutorials/) show how to achieve common and popular tasks with TablePress.
= Version 2.2.5 (January 30, 2024) =

* *Security fix*: The URL import now properly blocks hosts of cloud providers’ metadata API endpoints to prevent data extraction.
* When importing a table in the Excel format, floating point numbers are now detected and handled more reliably.
* The detection of the JSON format when importing a table is now more reliable.
* The “Copy”, “Export”, and “Delete” buttons/links on a table’s “Edit” screen now work again after a table ID was changed.
* Error messages when a table could not be found and similar are now shown properly in modern themes.
* The “Automatic Filtering” feature module now also allows using a slash in the filter term. (TablePress Pro and Max only.)
* The “Debug and Version Information” section was cleaned up and updated with more relevant checks.
* Updated external libraries to benefit from enhancements and bug fixes.
* Cleaned up and simplified code, for easier future maintenance, to follow WordPress Coding Standards, and to offer helpful inline documentation.

= Version 2.2.1 (November 2, 2023) =
= Version 2.2 (November 2, 2023) =
= 2.2.5 =
This update is a security and maintenance release. Updating is highly recommended.
 * @version 2.2.5
 * Version: 2.2.5
 * Copyright 2012-2024 Tobias Bäthge
if ( ! defined( 'TABLEPRESS_IS_PLAYGROUND_PREVIEW' ) ) {
	define( 'TABLEPRESS_IS_PLAYGROUND_PREVIEW', false );
}

				'anonymous_mode'    => TABLEPRESS_IS_PLAYGROUND_PREVIEW,
			array( '123.5', '123.5', 'Float with comma and period', '123.5' ),
			array( '3.022', '-0.162', 'Floats that can cause floating point precision errors with the General format 1', '0.579' ),
			array( '-3.022', '-0.051', 'Floats that can cause floating point precision errors with the General format 2', '0.094' ),
			<br />&middot; mySQL (Server): <?php echo isset( $GLOBALS['wpdb']->dbh ) ? mysqli_get_server_info( $GLOBALS['wpdb']->dbh ) : 'wpdb::$dbh not set'; // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info ?>
			<br />&middot; mySQL (Client): <?php echo mysqli_get_client_info(); // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_client_info ?>
			<br />&middot; mbstring: <?php echo extension_loaded( 'mbstring' ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
			<br />&middot; ZipArchive: <?php echo class_exists( 'ZipArchive', false ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
			<br />&middot; DOMDocument: <?php echo class_exists( 'DOMDocument', false ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
			<br />&middot; simplexml_load_string: <?php echo function_exists( 'simplexml_load_string' ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
			<br />&middot; libxml_disable_entity_loader: <?php echo function_exists( 'libxml_disable_entity_loader' ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
			<br />&middot; UTF-8 conversion: <?php echo ( function_exists( 'mb_detect_encoding' ) && function_exists( 'iconv' ) ) ? 'yes' : '<span style="color:#800000;font-weight:bold;">no</span>'; ?>
		if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) {
		if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) :
		echo "tp.nonces.copy_table = '" . wp_create_nonce( TablePress::nonce( 'copy_table', $data['table']['id'] ) ) . "';\n";
		echo "tp.nonces.delete_table = '" . wp_create_nonce( TablePress::nonce( 'delete_table', $data['table']['id'] ) ) . "';\n";
			echo '<a href="' . $preview_url . '" class="button button-large button-preview" target="_blank" data-shortcut="' . esc_attr( _x( '%1$sP', 'keyboard shortcut for Preview', 'tablepress' ) ) . '">' . __( 'Preview', 'tablepress' ) . '</a>';
			echo '<a href="' . TablePress::url( array( 'action' => 'copy_table', 'item' => $data['table']['id'], 'return' => 'edit' ), true, 'admin-post.php' ) . '" class="button button-copy">' . __( 'Copy Table', 'tablepress' ) . '</a> ';
			echo '<a href="' . TablePress::url( array( 'action' => 'export', 'table_id' => $data['table']['id'] ) ) . '" class="button button-export">' . __( 'Export Table', 'tablepress' ) . '</a> ';
			echo '<a href="' . TablePress::url( array( 'action' => 'delete_table', 'item' => $data['table']['id'], 'return' => 'edit', 'return_item' => $data['table']['id'] ), true, 'admin-post.php' ) . '" class="button button-delete delete-link">' . __( 'Delete Table', 'tablepress' ) . '</a>';
<form method="get">
<form method="get">