Skip to content

Fix issues table export.jquery.plugin deprecated #8070 - #8071

Merged
wenzhixin merged 8 commits into
wenzhixin:developfrom
marktech0813:Fix-issues-tableExport.jquery.plugin-deprecated-#8070
Oct 25, 2026
Merged

wenzhixin merged 8 commits into
wenzhixin:developfrom
marktech0813:Fix-issues-tableExport.jquery.plugin-deprecated-#8070

Conversation

@marktech0813

Copy link
Copy Markdown
Contributor

What I changed

  • Implemented a built-in exporter in src/extensions/export/bootstrap-table-export.js that:
    Supports types: json, xml, csv, txt, sql, and maps excel to CSV (.xls).
    Preserves existing behaviors: fileName function support, footer export, column visibility (forceExport/forceHide), selected/all/basic export, and detail-view column exclusion via ignoreColumn.
    Uses safe Blob download, avoiding deprecated/vulnerable plugin code.
  • Updated docs in site/src/pages/docs/extensions/export.mdx:
    Removed plugin requirement.
    Documented built-in options (fileName, csvDelimiter, tableName) and supported types.
  • Updated CONTRIBUTING.md to reflect that Table Export is now built-in.

Notes

  • Users no longer need to include the deprecated plugin; exports work out of the box.
  • If you publish new artifacts, run the build to regenerate dist/ so consumers loading from dist/ get the changes.
    Status: I replaced the plugin with a built-in exporter, updated docs, and removed references.
    I removed the deprecated tableExport.jquery.plugin usage and implemented a built‑in exporter.

Contribution by Gittensor, learn more at https://gittensor.io/

Updated CONTRIBUTING.md to reflect that Table Export is now built-in.
Updated docs in site/src/pages/docs/extensions/export.mdx:
- Removed plugin requirement.
- Documented built-in options (fileName, csvDelimiter, tableName) and supported types.
Implemented a built-in exporter in src/extensions/export/bootstrap-table-export.js that:
- Supports types: json, xml, csv, txt, sql, and maps excel to CSV (.xls).
- Preserves existing behaviors: fileName function support, footer export, column visibility (forceExport/forceHide), selected/all/basic export, and detail-view column exclusion via ignoreColumn.
- Uses safe Blob download, avoiding deprecated/vulnerable plugin code.

Contribution by Gittensor, learn more at https://gittensor.io/
@marktech0813

Copy link
Copy Markdown
Contributor Author

Please check PR.
thanks.

@ajiho

ajiho commented Nov 15, 2025

Copy link
Copy Markdown

That's awesome!

…ixin#8071

Refactor CSV escaping and table matrix collection logic for improved readability and null handling.

- Using strict equality checks for null/undefined.
- Adding required blank lines between declarations and control statements.
- Removing unnecessary arrow parens and extra parentheses.
- Using template literals instead of string concatenation.
- Ensuring single quotes and proper brace style.
- Splitting multi-statements onto separate lines.
@marktech0813

Copy link
Copy Markdown
Contributor Author

I fixed, Please check PR again,
thanks.

@fsay2604

Copy link
Copy Markdown

Nice! Any idea when/if it will be merge?

@MartinPerrie

Copy link
Copy Markdown

Same question as @fsay2604 ! Any idea when this might be merged? I hit an issue with jQuery 4, where the the "trim" function has been removed. This function is used by tableexport.jquery.plugin - so the Export extension won't work with jQuery 4.

@marktech0813
marktech0813 marked this pull request as draft February 9, 2026 14:38
@marktech0813
marktech0813 marked this pull request as ready for review February 9, 2026 14:38
@simonsolutions

Copy link
Copy Markdown
Contributor

+1 for review, this is a great change to not rely on external (and now deprecated) repos. Well done <3

@wenzhixin
wenzhixin requested a review from Copilot February 17, 2026 15:33
@wenzhixin

Copy link
Copy Markdown
Owner

Okay, I will review and conduct test verification as soon as possible.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Replaces the deprecated tableExport.jquery.plugin dependency with a built-in export implementation in the export extension, and updates documentation/contribution guidance accordingly.

Changes:

  • Implemented built-in export generation + Blob download for json, xml, csv, txt, sql, and legacy excel (mapped to CSV content with .xls extension).
  • Updated export extension docs to remove the external plugin requirement and document built-in options/types.
  • Updated CONTRIBUTING dependency list to reflect the built-in exporter.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
src/extensions/export/bootstrap-table-export.js Replaces plugin-based export with built-in content builders and a Blob-based download flow.
site/src/pages/docs/extensions/export.mdx Updates docs to describe built-in exporter options and supported types.
CONTRIBUTING.md Updates dependency documentation for the export extension.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +183 to +190
const csvEscape = (value, delimiter) => {
const d = delimiter || ','

if (value === null || value === undefined) return ''

const str = String(value)
const mustQuote = str.includes(d) || str.includes('"') || str.includes('\n') || str.includes('\r')

Copilot AI Feb 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The added helper code introduces trailing whitespace on blank lines (e.g., around this block). ESLint is configured with no-trailing-spaces: 'error' (eslint.config.js:85), so this will fail lint. Please remove the trailing spaces (or run the project formatter/linter autofix) in the new code.

Copilot uses AI. Check for mistakes.
Comment on lines +287 to +288
const lines = ['<?xml version="1.0" encoding="UTF-8"?>', `<${tableName}>`]

Copilot AI Feb 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tableName is interpolated directly as the XML root element name. If exportOptions.tableName contains spaces or other invalid XML name characters, the generated XML becomes invalid. Please sanitize/normalize tableName to a safe XML element name (and fall back to a default when it cannot be made valid).

Copilot uses AI. Check for mistakes.
Comment on lines +291 to +294
r.forEach((v, i) => {
const key = headerRow[i] || `col${i + 1}`
lines.push(` <${key}>${esc(v)}</${key}>`)
})

Copilot AI Feb 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XML element names are derived from header text (key = headerRow[i]). Header labels commonly contain spaces/special characters, which produces invalid XML tags like <First Name>. Please normalize header-derived keys into valid XML element names (e.g., replace invalid characters, ensure a valid starting character) and fall back to colN when needed.

Copilot uses AI. Check for mistakes.
Comment on lines +304 to +310
const values = rows.map(r => `(${r.map(v => {
if (v === null || v === undefined || v === '') return 'NULL'
const s = String(v).replace(/'/g, '\'\'' )
return `'${s}'`
}).join(', ')})`)

const sql = `INSERT INTO \`${tableName}\` (\`${cols.join('`, `')}\`) VALUES\n${values.join(',\n')};`

Copilot AI Feb 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the SQL export, tableName is used inside backticks without escaping backticks in the name, and when rows is empty the generated statement becomes VALUES\n; (invalid SQL). Please escape backticks in tableName similarly to column names, and handle the no-rows case by returning an empty string/file or a comment instead of an invalid INSERT.

Suggested change
const values = rows.map(r => `(${r.map(v => {
if (v === null || v === undefined || v === '') return 'NULL'
const s = String(v).replace(/'/g, '\'\'' )
return `'${s}'`
}).join(', ')})`)
const sql = `INSERT INTO \`${tableName}\` (\`${cols.join('`, `')}\`) VALUES\n${values.join(',\n')};`
// If there are no rows, avoid generating an invalid INSERT statement.
if (!rows.length) {
return { mime: 'application/sql;charset=utf-8', ext: 'sql', content: '' }
}
const values = rows.map(r => `(${r.map(v => {
if (v === null || v === undefined || v === '') return 'NULL'
const s = String(v).replace(/'/g, '\'\'' )
return `'${s}'`
}).join(', ')})`)
const safeTableName = String(tableName).replace(/`/g, '``')
const sql = `INSERT INTO \`${safeTableName}\` (\`${cols.join('`, `')}\`) VALUES\n${values.join(',\n')};`

Copilot uses AI. Check for mistakes.
Comment on lines +428 to +432
if (!built) {
// unsupported type without deprecated plugin; no-op but still restore state
onAfter()
return
}

Copilot AI Feb 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the export type is unsupported, doExport silently no-ops and restores state, but the caller still fires the export-saved event, which is misleading because no file was produced. Please have doExport return a success/failure flag (or throw/trigger an error event) so unsupported types can avoid emitting export-saved and optionally notify the user.

Copilot uses AI. Check for mistakes.
@wenzhixin

Copy link
Copy Markdown
Owner

Hi @marktech0813, thanks for working on this! Replacing the deprecated plugin with a built-in exporter is a much-needed change. I've reviewed the PR in detail and have some feedback:

Key Issues

1. Data collection via DOM parsing instead of data API

collectTableMatrix() reads table content from the DOM using $(td).text().trim(). This approach has several problems:

  • It only captures the display text, not the original data values (e.g., formatted numbers, dates get exported as display strings, not raw values)
  • It conflicts with the existing forceExport/forceHide logic — the code still calls showColumn/hideColumn to manipulate which columns are visible, but the actual data collection walks the DOM independently
  • It may produce inconsistent results depending on current sort/filter state

I'd recommend collecting export data from bootstrap-table's internal data model (getData(), getVisibleFields(), column definitions with field, formatter etc.) rather than scraping the rendered DOM.

2. Export type reduction is a breaking change

The plugin previously supported 10 types (json, xml, png, csv, txt, sql, doc, excel, xlsx, pdf). This PR reduces it to 6, dropping png, xlsx, pdf, doc, and powerpoint. For users who rely on PDF or Excel exports, this is a breaking change.

Would you consider keeping optional support for these types via lightweight libraries (e.g., SheetJS for xlsx, jsPDF for pdf)?

3. excel type is misleading

The excel type generates CSV content but uses a .xls extension. This causes Excel to show a format warning when opening the file. It's not a real Excel file — please consider being upfront about this in the docs, or use .csv extension instead.

Copilot Review Items (agreed)

The Copilot review raised valid points that should be addressed:

  1. Trailing whitespace — ESLint will fail with no-trailing-spaces: 'error'
  2. XML tag names from headers — Headers with spaces (e.g., "First Name") produce invalid XML tags like <First Name>. Header-derived tag names should be sanitized to valid XML element names, falling back to colN
  3. tableName in XML root — Should be sanitized for valid XML element names
  4. SQL export edge cases — tableName not escaped for backticks; empty rows produce invalid INSERT statement (VALUES\n;). Should return empty content when no rows exist
  5. Unsupported types silently no-op — When an unsupported type is passed, export-saved event still fires even though no file was produced. Should return a flag or skip the event

Missing Updates

  • Chinese docs not updated — Only the English export.mdx was updated. site/src/pages/zh-cn/docs/extensions/export.mdx still references the old plugin
  • Cypress tests need rewriting — cypress/extensions/export/options.js (line 184-211) mocks $.fn.tableExport and asserts the plugin was called. These tests need to be updated to verify the built-in exporter behavior instead

Summary

The direction is right and this PR is much needed (especially for jQuery 4 compatibility). The main concern is the DOM-based data collection approach — switching to a data-API-driven approach would make the exporter more robust and consistent with the rest of bootstrap-table's architecture.

wenzhixin and others added 4 commits October 25, 2026 11:27
Collect export data from the table data model instead of scraping the
rendered DOM, so the exported values match what is rendered by the table
formatters while keeping the original value types available.

- validate the export type up front and skip unsupported ones without
  triggering any export event
- export the current page only for the basic data type
- sanitize xml element names and escape sql identifiers
- return empty sql content instead of an invalid INSERT statement

Co-authored-by: marktech0813 <178346048+marktech0813@users.noreply.github.com>
…zhixin#8071)

Cover the built-in exporter with unit tests through a mocked download and
rewrite the cypress export tests, which still asserted that the removed
tableExport.jquery.plugin was called.

Co-authored-by: marktech0813 <178346048+marktech0813@users.noreply.github.com>
…8071)

Document the exportOptions supported by the built-in exporter, the removed
plugin options and types, the basic data type exporting the current page
and the excel type generating CSV content with an xls extension.

Co-authored-by: marktech0813 <178346048+marktech0813@users.noreply.github.com>
@wenzhixin

Copy link
Copy Markdown
Owner

Hi @marktech0813, thank you again for starting this work. Since this PR has had no activity since 2025-11-19, I took it over as maintainer and pushed the remaining fixes to your branch, keeping your original commits intact.

All review feedback has been addressed:

Data collection via DOM parsing (issue 1)
collectTableMatrix() is gone. Export data is now collected from the table data model through two new instance methods, getExportColumns() and collectExportData(data):

  • columns are taken from this.columns honoring visible / forceExport / forceHide, skipping the checkbox/radio state column and colspan columns
  • cell values use the same pipeline as the body renderer (Utils.getItemField + the column formatter), then strip HTML to plain text, so the export matches what is displayed while cell values keep their original type for SQL/JSON
  • the footer is built with getFooterData() + footerFormatter instead of cloning a fake tbody row
  • all the DOM show/hide choreography (hideColumn/showColumn/toggleView/ignoreColumn) was removed

Copilot review items

  1. Trailing whitespace: the affected block was replaced entirely.
  2. XML tag names derived from columns: tags are sanitized to valid XML names, falling back to colN and de-duplicating collisions.
  3. tableName in the XML root element: sanitized the same way.
  4. SQL edge cases: identifiers escape doubled backticks, and empty data produces empty content instead of an invalid VALUES\n; statement.
  5. Unsupported types: validation now happens before any event is triggered, so exportTable() returns false, warns once and neither saves a file nor fires export-started / export-saved.

Export type reduction (issue 2)
We deliberately do not add SheetJS or jsPDF: the goal of this change is jQuery 4 compatibility and dropping the deprecated plugin, and we do not want to introduce new third-party dependencies that every user has to ship. png, pdf, xlsx, doc and powerpoint are therefore no longer supported by the built-in exporter; users needing them should pair getData() with the library of their choice. This is documented as a migration note in both the English and Chinese docs.

Misleading excel type (issue 3)
Kept for backwards compatibility, but explicitly documented (en + zh-cn) as CSV content with a .xls extension, including the Excel format warning.

Missing updates

  • Chinese docs: fully synced with the English version, old plugin dependency section removed.
  • Cypress: exportTable() tests no longer mock $.fn.tableExport, they stub URL.createObjectURL and assert on the produced Blob content; added a test covering unsupported types; the plugin CDN script was dropped from the export fixtures.

Additional changes: basic now explicitly exports the current page only (getData({ useCurrentPage: true })), exportOptions (fileName / csvDelimiter / tableName) is documented, and unit tests were added under tests/extensions/export.test.js.

@wenzhixin wenzhixin left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again @marktech0813 for kicking this off. The data-API driven exporter looks good: DOM scraping is gone, the review items (xml/sql sanitization, unsupported types, cypress and Chinese docs) are addressed and CI is green. Approving and merging.

@wenzhixin
wenzhixin merged commit 0679534 into wenzhixin:develop Oct 25, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants