From 967801e2b8427c734de40b38569801c22f7210f7 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Thu, 30 May 2019 14:59:10 +0200 Subject: [PATCH] ox: Make `org-export-table-cell-width' more robust * lisp/ox.el (org-export-table-cell-width): Make `org-export-table-cell-width' robust against malformed tables. Reported-by: michael --- lisp/ox.el | 46 +++++++++++++++++++++++------------------ testing/lisp/test-ox.el | 45 ++++++++++++++++++---------------------- 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/lisp/ox.el b/lisp/ox.el index 054e10fb7..f7b01daa4 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -4916,26 +4916,32 @@ same column as TABLE-CELL, or nil." (plist-put info :table-cell-width-cache table) table))) (width-vector (or (gethash table cache) - (puthash table (make-vector columns 'empty) cache))) - (value (aref width-vector column))) - (if (not (eq value 'empty)) value - (let (cookie-width) - (dolist (row (org-element-contents table) - (aset width-vector column cookie-width)) - (when (org-export-table-row-is-special-p row info) - ;; In a special row, try to find a width cookie at COLUMN. - (let* ((value (org-element-contents - (elt (org-element-contents row) column))) - (cookie (car value))) - ;; The following checks avoid expanding unnecessarily - ;; the cell with `org-export-data'. - (when (and value - (not (cdr value)) - (stringp cookie) - (string-match "\\`<[lrc]?\\([0-9]+\\)?>\\'" cookie) - (match-string 1 cookie)) - (setq cookie-width - (string-to-number (match-string 1 cookie))))))))))) + (puthash table (make-vector columns 'empty) cache)))) + ;; Table may not have the same number of rows. Extend + ;; WIDTH-VECTOR appropriately if we encounter a row larger than + ;; expected. + (when (>= column (length width-vector)) + (setq width-vector + (vconcat width-vector + (make-list (- (1+ column) (length width-vector)) + 'empty))) + (puthash table width-vector cache)) + (pcase (aref width-vector column) + (`empty + (catch 'found + (dolist (row (org-element-contents table)) + (when (org-export-table-row-is-special-p row info) + ;; In a special row, try to find a width cookie at + ;; COLUMN. The following checks avoid expanding + ;; unnecessarily the cell with `org-export-data'. + (pcase (org-element-contents + (elt (org-element-contents row) column)) + (`(,(and (pred stringp) cookie)) + (when (string-match "\\`<[lrc]?\\([0-9]+\\)>\\'" cookie) + (let ((w (string-to-number (match-string 1 cookie)))) + (throw 'found (aset width-vector column w)))))))) + (aset width-vector column nil))) + (value value)))) (defun org-export-table-cell-alignment (table-cell info) "Return TABLE-CELL contents alignment. diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 3bd26224d..71a70bf73 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -4148,33 +4148,28 @@ Another text. (ref:text) (ert-deftest test-org-export/table-cell-width () "Test `org-export-table-cell-width' specifications." - ;; 1. Width is primarily determined by width cookies. If no cookie - ;; is found, cell's width is nil. - (org-test-with-parsed-data " + ;; Width is primarily determined by width cookies. If no cookie is + ;; found, cell's width is nil. + (should + (equal '(nil 6 7) + (org-test-with-parsed-data " | / | | <6> | | | | a | b | c |" - (should - (equal - '(nil 6 7) - (mapcar (lambda (cell) (org-export-table-cell-width cell info)) - (org-element-map tree 'table-cell 'identity info))))) - ;; 2. The last width cookie has precedence. - (org-test-with-parsed-data " -| <6> | -| <7> | -| a |" - (should - (equal - '(7) - (mapcar (lambda (cell) (org-export-table-cell-width cell info)) - (org-element-map tree 'table-cell 'identity info))))) - ;; 3. Valid width cookies must have a specific row. - (org-test-with-parsed-data "| <6> | cell |" - (should - (equal - '(nil nil) - (mapcar (lambda (cell) (org-export-table-cell-width cell info)) - (org-element-map tree 'table-cell 'identity)))))) + (mapcar (lambda (cell) (org-export-table-cell-width cell info)) + (org-element-map tree 'table-cell 'identity info))))) + ;; Valid width cookies must have a specific row. + (should + (equal '(nil nil) + (org-test-with-parsed-data "| <6> | cell |" + (mapcar (lambda (cell) (org-export-table-cell-width cell info)) + (org-element-map tree 'table-cell 'identity))))) + ;; Do not error on malformed tables. + (should + (org-test-with-parsed-data " +| a | +| b | c |" + (mapcar (lambda (cell) (org-export-table-cell-width cell info)) + (org-element-map tree 'table-cell 'identity info))))) (ert-deftest test-org-export/table-cell-alignment () "Test `org-export-table-cell-alignment' specifications."