@@ -278,9 +278,7 @@ function buildListPath(level, map) {
278278 * @param {HTMLElement } container
279279 */
280280function convertStyledHeadings ( container ) {
281- const paragraphs = Array . from ( container . querySelectorAll ( 'p' ) ) . filter (
282- ( p ) => p . parentElement ?. tagName ?. toLowerCase ( ) !== 'li' ,
283- ) ;
281+ const paragraphs = Array . from ( container . querySelectorAll ( 'p' ) ) . filter ( ( p ) => ! p . closest ( 'li' ) ) ;
284282
285283 paragraphs . forEach ( ( p ) => {
286284 const { fontSize, isBold } = getHeadingStyleProps ( p ) ;
@@ -300,23 +298,42 @@ function convertStyledHeadings(container) {
300298
301299/**
302300 * Reads font-size (in pt) and bold status from an element's inline style.
303- * Checks both the element itself and its first child <span> to cover both
304- * Google Docs style placements (style on <p> vs. style on inner <span>).
301+ * When font-size is on the <p>, bold is accepted from the <p> or all child
302+ * spans. When font-size is only on child spans, all spans must share the same
303+ * size; bold status is reported as whether all spans are bold.
305304 *
306305 * @param {HTMLElement } el
307306 * @returns {{ fontSize: number|null, isBold: boolean } }
308307 */
309308function getHeadingStyleProps ( el ) {
310- const fontSize = parsePtValue ( el . style . fontSize ) ;
311- const isBoldOnEl = boldWeightRegex . test ( el . style . fontWeight || '' ) ;
309+ const elFontSize = parsePtValue ( el . style . fontSize ) ;
310+ const spans = Array . from ( el . querySelectorAll ( 'span' ) ) ;
311+ const allSpansBold = spans . every ( ( span ) => boldWeightRegex . test ( span . style . fontWeight || '' ) ) ;
312+ const notHeading = { fontSize : null , isBold : false } ;
313+
314+ // font-size declared on <p>: bold from <p> itself or if all child spans are bold
315+ const fromElement = ( ) => ( {
316+ fontSize : elFontSize ,
317+ isBold : boldWeightRegex . test ( el . style . fontWeight || '' ) || ( spans . length > 0 && allSpansBold ) ,
318+ } ) ;
319+
320+ // font-size only on child spans: all must be same size and bold
321+ const fromSpans = ( ) => {
322+ // no span children, size is indeterminate
323+ if ( spans . length === 0 ) return notHeading ;
312324
313- const { children } = el ;
314- const singleSpan = children . length === 1 && children [ 0 ] . tagName ?. toLowerCase ( ) === 'span' ? children [ 0 ] : null ;
325+ // if not all spans declare a font-size, not a heading
326+ const sizes = spans . map ( ( span ) => parsePtValue ( span . style . fontSize ) ) ;
327+ if ( sizes . some ( ( size ) => size === null ) ) return notHeading ;
315328
316- return {
317- fontSize : fontSize ?? parsePtValue ( singleSpan ?. style . fontSize ) ,
318- isBold : isBoldOnEl || boldWeightRegex . test ( singleSpan ?. style . fontWeight || '' ) ,
329+ // if inconsistent sizes, mixed body text, not a heading
330+ const [ firstSpanSize ] = sizes ;
331+ if ( sizes . some ( ( size ) => size !== firstSpanSize ) ) return notHeading ;
332+
333+ return { fontSize : firstSpanSize , isBold : allSpansBold } ;
319334 } ;
335+
336+ return elFontSize !== null ? fromElement ( ) : fromSpans ( ) ;
320337}
321338
322339/**
0 commit comments