From 280a02150e2345f8690e495b6a447ba1c1b3b5dd Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Tue, 3 Feb 2026 21:54:45 +0100 Subject: [PATCH] In tagged pdfs, TH can be either a column header or a row header (bug 2014080) --- test/integration/accessibility_spec.mjs | 67 ++++++++++++++++++++++++ test/pdfs/.gitignore | 1 + test/pdfs/bug2014080.pdf | Bin 0 -> 33325 bytes web/struct_tree_layer_builder.js | 19 +++++-- 4 files changed, 82 insertions(+), 5 deletions(-) create mode 100755 test/pdfs/bug2014080.pdf diff --git a/test/integration/accessibility_spec.mjs b/test/integration/accessibility_spec.mjs index 2c04b5f00..8d78d7fb6 100644 --- a/test/integration/accessibility_spec.mjs +++ b/test/integration/accessibility_spec.mjs @@ -544,4 +544,71 @@ describe("accessibility", () => { ); }); }); + + describe("A TH in a TR itself in a TBody is rowheader", () => { + let pages; + + beforeEach(async () => { + pages = await loadAndWait("bug2014080.pdf", ".textLayer"); + }); + + afterEach(async () => { + await closePages(pages); + }); + + it("must check that the table has the right structure", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + let elementRole = await page.evaluate(() => + Array.from( + document.querySelector(".structTree [role='table']").children + ).map(child => child.getAttribute("role")) + ); + + // THeader and TBody must be rowgroup. + expect(elementRole) + .withContext(`In ${browserName}`) + .toEqual(["rowgroup", "rowgroup"]); + + elementRole = await page.evaluate(() => + Array.from( + document.querySelector( + ".structTree [role='table'] > [role='rowgroup'] > [role='row']" + ).children + ).map(child => child.getAttribute("role")) + ); + + // THeader has 3 columnheader. + expect(elementRole) + .withContext(`In ${browserName}`) + .toEqual(["columnheader", "columnheader", "columnheader"]); + + elementRole = await page.evaluate(() => + Array.from( + document.querySelector( + ".structTree [role='table'] > [role='rowgroup']:nth-child(2)" + ).children + ).map(child => child.getAttribute("role")) + ); + + // TBody has 5 rows. + expect(elementRole) + .withContext(`In ${browserName}`) + .toEqual(["row", "row", "row", "row", "row"]); + + elementRole = await page.evaluate(() => + Array.from( + document.querySelector( + ".structTree [role='table'] > [role='rowgroup']:nth-child(2) > [role='row']:first-child" + ).children + ).map(child => child.getAttribute("role")) + ); + // First row has a rowheader and 2 cells. + expect(elementRole) + .withContext(`In ${browserName}`) + .toEqual(["rowheader", "cell", "cell"]); + }) + ); + }); + }); }); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 7d924f753..73665e3be 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -872,3 +872,4 @@ !page_with_number_and_link.pdf !Brotli-Prototype-FileA.pdf !bug2013793.pdf +!bug2014080.pdf diff --git a/test/pdfs/bug2014080.pdf b/test/pdfs/bug2014080.pdf new file mode 100755 index 0000000000000000000000000000000000000000..1fc44d80d27d1542a318ecd07de3d8fad581c5d9 GIT binary patch literal 33325 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

H>fmP(gBZC}G}DQ;;xZ-@74RuU+Ay$2E z^R~SD!=@zuk`Z?HNFtGQS|VmM>CA=6`Mw(rqGaiIsa~X`p)!`^2ZHf3rS+g`V#e3+ z4$Ukc^his{AA7}ocD-tBLQcViy5A~^L(%_$g3UDlDJ3&Ao-b3_#oaz~s z;RX~}$XYcZ?RTlG6iFj`wZ2w<+FO78iJi5!X{xZzq>X~T`FTHIbW#TK{SIBHw};xo zXnj)OktTJwYnD)4GH(eLZ9JMN6Cz?ik96sUTmZ9vL7ycGdg-h6>3%ygO=wMTuoj^s z&nGFNR=uZu_+Kt-HMUI2-PqviTZ5WTPCwz2>4e11q6KjYbMOU}#WyixJf)1V*~oim zG*=YxnRem(}~(mgW{`J8{Hp5wYC<8H!s{G z4B+Y>Pg!D}b)yNzbMck10PMIV&1ZdKC%5r#V$6dK!V&l7LJYT(F)?Vi-YwoZynHae zhc3PI`t99}1hoa(Vs!hmxAV7mSn!zQ4n=l+L38VLY9lctBXHj(Qx|=vz#*~Y#Yq}e zmvhYQ2&0&KIQ^Z7?1qj`vA3e{us&+;V`7^74Nqfu26|Q0406LoFyRRnL^SO4kwPER zY=@r>`#wb_Ucdh;Er#DW*%BGP$`?BBUT@4R^Fi|Ragv1?Fd)g7L4NV zwhV;<61TiInTzT2^p^2UPg-s=<(>F^R;gQUaSddti1o3a!KS@hSuxO~uF`jG6npTR z(@l+2PJpi6_p#hQCP@*!!ft50G}Gsl)R3-)P{9nb>JlG{Ij5dYBGN=!``t}hkMLD~ zlr1)gjs+@SWU>t@MgYrFXMo%>pt}%Ga%s?<_0G3}Y{BVQX;mD}LG7Ss!aEym`-RPvU!z2ZmiD5;<^->jWu-1{Dj#+FJrhB>Y` zL0H&_k3JJo*Dlk2i^moB(Sf0Gb6#+LePUPbF8|uP5KdCFjM6%j+I=m6%J^Fi@&G#w2Y`x%K zlio!%_e+!!*!pAnXb;}8-X+Hk#^lrvzrzyzy1BEpv!x1q4ZVi!TabZ8>+@-w>E(@0 zG}<wD?5tZSW_I%O7u-)Zlv0k*rL$QOeASR>>V%7-~>4H>vq{ zwXZ;Pw@slyDXBfqQ4xzl-U zbu%uuWAyRIQXA8G1(S;5B#MUKPLBKgt~u-1lVW-`{3>zB3%0^0hhoP|w$vuKIt|$> zRkD}%6H*-Ps!A8tWjXx8pWIF6N7=qRKP|4^jdd1$I)8EfSOAOF)gZu7{!xKpM=!Uh z`_u)5-|Oh|Dxau5)?>8jIgf(yLb0AxQaPN7EoU-NH$@plU$& z;sL>wc&(IwZLja+kA?AJ-mQwa{UC#KEnHr~gJkHbSs(&wNkTahdk* zJPm!}z?#R>QVWD|ie7-(J}VtdCObI}Pme?(odxgNH9S?xETohWM~eDwJZZlt+y}e` zfe2|?kqbGde)m^-TKf=+=|H0+1u6eQZ@6gVwXUp$Bw}6KS(%WamLj^Yx_A7&Ql)rD zB2^h*$wCKMKj>t9^qACc4|$emJ6*r!nZFKVS}3WwBl9UYc$YG_doz!KS^wezt%-AC>OBwS>tr6kVu;7hQt;v?Yh<(Qx?4uCCywS)uqE6i zGPbQ;ZP|(4S>=HVwWljrp(=9;CthROyiL=P_syjIN^!|f?@h0foJ^TF$Aw*Ab|siKT)tA!U#*40E?yc-*TD?HY8kE88tU zRbSwJSCeCRe%{CG9?^2WS4PLz$o)lpxYz>y1kG=>ziGcVB+%R<;eT&@D4_wQ4})!$ zG;5i+tk}d@>(G+8>;yO-OnUPK;$0^#3BXTy@l9z7_3ndB%uVF8d_9n>Ftu9~Pj@-r zed|_4H*C1~Dbpm}Ko36Y-~2UPX^Y1M!WTd;lQQy(b6{$3HYW1bAO)+uCjRu}&oqWM zaJ+2VhyiJpWW9mJ?CD@yXxAm=R*tKx2t>J_`?GpiW+ZD6eClRUf1wt4@mvDOLL@>I zI=@NdhgvXPWX{x8!G>>X6xZDjU|KD042%oABK)+2RtIGDwVbzh^KH|RV0&gsCGG1J z=xU1=OPqLGf=rv`{-dINHOtYP)XRQSqN%U@F^WH1F5EG!`DkVv>9SSkAWZ|kUjLP7 z*s*J){PB`gPQ^8Ce`6nY%}k@&)pyBZTCiL4X&KA8eeLi*Qc%crWDu&BI8Up-Pdd#l zY>no+VgY%cJpJ%h&4a+ga(cV!80R5YmgUi?C)xR2W=#nhCl9EH`0U)mX0ID13Fc{a zEo6;K962=0!?z#XR2s03s#e0uo{m*&vI}g*dfiA%Ti=b0=f(aO3PSnFGMYJnUhg6B zUlzED!8yL(o$_o#_4o-HNr!ZOeP*0wM@0RFbg)6jsd%Cbk`1%pG zluUkVOCg1+`%qLS0gvXft$Vbqwk6&z8@_y`Khy++MdBOkIGi~rHTG)^t-Lwvz_-v) zb11X=`{!H;1q{A{z zONh>cL+c_`ms;3l#WXp~0gm`kXkH%h!iCw_E&dy~Ci_xLOz&ncHrOjGT7kO_kv-EC!l+z`{bi5XG*qC)INWf=4U z;pX%D1;2_hK4C?vmiK;JFC8t#$B+}nH&x`bNUl9tCvfJ@?Fqxxej23f#PI~2irag` z8hV)^8#AjGySmlM+Ew|c0Kz2Wi%;ChtB8&{okG)_w#F~_(Mea0iKS|YHP+Iqg=!q7 zOA(2y_5J^Q+koWnbEdzT)@8UYD+#h^EYQws4+mU*wur!CYUVT`?^I#Qd3 zBMmVtOB{ptnAa93v1+hBD|#xv9Q61Q5KzOd^I>YqgXTq*JaOsV5| J`_q+oSb6 z_1b1F9}-fMAO>O2~RCbZy2{nbVQndwaF7OR}1O7GUzdGTa9s; zdmx4sTLD_vjY@e2eG0;ex1ESMu-Uzev|&HAj(2b;bg4bMu_m!Afoxl8s}cI-4)|6l zwQI3b?RjFQjiqHfk#UfEAcWLh(X5-VQ9}k2=#D*DVnugwu*cZ7-$DPd@(8~o)dqj9 zywk2Gr4wYCQh8%((!n@+&SAB&rxHS9eFf*;3>2q$iO>F>)?*Q|8XT= zxcZAL_Lflj31(GsUQN-+#BTb7|!KW25KWblKKMv1qLC>T>X$$m+^t2)d3OXy9fdNy1Ik|wc znX>{JZlLG|3OyUj4d{bTd;9-UHUm4Wl{qV$fr9@~0&|^Of}T3?ql)ItKKRr=7<^V{ zb5>BpbLux3dO8*8w6+F(1`&E{8_WX+FoI5J1oHqGA!o)QU_c7+6aZ45Q@Bttrns@IQaDYOEJ$+%oJzJKNa)*++Y2y&GDZ+ zS%38kzb`NMCj%3hlL!8DQ3t<}qvaDl69Zd1U4RMmL=UddASB4|$m?ikX$H`7(K(u#n%nR?3NSo5C6wR=j!(rL40LBI zwk84$V0JDxZcZ)+K^%T-{inRj;*x(10{#97O9-q1DF5l;{|w;g zIGy+>NB#i!ljL02^!5HiY-wk0dWKhDkHg>x1BVUZ9oLz6`g**2Ke~tuo&`}vI=m=1jaItfqc?l@-{?Y7Q73fd#Ukc-| zWBC6P7@W2*7d&lm&c+F1;{>aMIC-I5K)-XK$2l)2CqKt8nr9<{uII*25&xBuKWYAV z&mQ1_y!`(;EM{hZMn+zqSKLC+?vziTEl`f=F@l5ZeW{40AG{7?1|P?-rZH~_i* z`8R(*^UD1}xd&u7s;5*ff3WlZbVKqRanXHcgQpxS#!d#n9UzAW(2fA$p*^LgJ!1hr z5!d7gOG3nfYzat|M7epuK&}KNNwTBEwu}9=lSz( zkYfzAM@9kt36bway!zGXMB+T+JTfaZLr+SM3G!Uw%O>blicdy94f>e#cnx;vU~w|O zn?*UNkZ->a$$YPD@ai?^tFKE}3nnq#yj6(TXn;bYqb z<75tOjy{T3LZr`qC>17TUZEOUFHG<;mY#cV9RdDid>l?XI4AJ;j}O4i41+?!P`cA! z{`i~{f1Q5l%>R-BFY5dz0|BFc)q{e6(*tq+t_K2f1C1&EJ_m4~fCci43<3jghkucs zHwQP*?|M8Cfa&U&u{>~~LBiiygFw!a{T>%E4E$UCz}%~2MF!*m{IXOYl-_I`yc8-ku92w6!GWhQ@Fy}cku5)Cd zb7bIiWaq3&U=97YPQmBk0Al~U-Z?mcb^4nguwH(bor42%4i3mUI3VZXfSiK^at;p2 zIXEEa-~iUpZ$3lM!2vx72lN~qz*Dr}?VW=IdJYcgIXIx_;DDZk19}b)*f}_0=iq>y zg9COB4%j(3VCUcf_MG2h06PZ<>>L~bIoWSxxzE7?>^Z;dor43|Cx6#F2M6~#IJnQj z!F>)6?sISeyZDK=1ynqZ?e}CDtwSEE+#9HIy@bmx3Ti~4k&y$rO z>Btjn+aDKXFc%jOz`Vr7B%vsYkMrk68n{OP|L~1N$=bl4?#v~Q(_{`{(E}dE10nm> MY2Yb4><_2^7kUbLT>t<8 literal 0 HcmV?d00001 diff --git a/web/struct_tree_layer_builder.js b/web/struct_tree_layer_builder.js index 8f561eac5..b1bf2189e 100644 --- a/web/struct_tree_layer_builder.js +++ b/web/struct_tree_layer_builder.js @@ -61,8 +61,8 @@ const PDF_ROLE_TO_HTML_ROLE = { TR: "row", TH: "columnheader", TD: "cell", - THead: "columnheader", - TBody: null, + THead: "rowgroup", + TBody: "rowgroup", TFoot: null, // Standard structure type Caption Caption: null, @@ -353,7 +353,7 @@ class StructTreeLayerBuilder { } } - #walk(node) { + #walk(node, parentNodes = []) { if (!node) { return null; } @@ -378,7 +378,14 @@ class StructTreeLayerBuilder { element.setAttribute("role", "heading"); element.setAttribute("aria-level", match[1]); } else if (PDF_ROLE_TO_HTML_ROLE[role]) { - element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]); + element.setAttribute( + "role", + role === "TH" && + parentNodes.at(-1)?.role === "TR" && + parentNodes.at(-2)?.role === "TBody" + ? "rowheader" // TH inside TR itself in TBody is a rowheader. + : PDF_ROLE_TO_HTML_ROLE[role] + ); } if (role === "Figure" && this.#addImageInTextLayer(node, element)) { return element; @@ -423,9 +430,11 @@ class StructTreeLayerBuilder { // parent node to avoid creating an extra span. this.#setAttributes(node.children[0], element); } else { + parentNodes.push(node); for (const kid of node.children) { - element.append(this.#walk(kid)); + element.append(this.#walk(kid, parentNodes)); } + parentNodes.pop(); } } return element;