Skip to content

Bold on Hebrew/Arabic runs is lost: w:bCs is parsed but never rendered #3959

Description

@Nathaniel-260

What happened?

A Hebrew document whose headings are bold in Microsoft Word renders at normal
weight in SuperDoc.

Hebrew and Arabic Word writes bold-for-complex-script as w:bCs alone whenever the
styled selection is single-script — it does not add w:b. Word renders such a run
bold. SuperDoc reads only w:b, so the bold is lost.

This is the heading style from the document I hit it on (a Hebrew Torah-study text):

<w:style w:type="paragraph" w:styleId="2">
  <w:name w:val="heading 2"/>
  <w:rPr>
    <w:rFonts w:ascii="FrankRuehl DP" w:hAnsi="FrankRuehl DP" w:cs="FrankRuehl DP"/>
    <w:bCs/>                      <!-- no <w:b/> -->
    <w:szCs w:val="28"/>
  </w:rPr>
</w:style>

Its runs carry <w:rtl/>. All ten headings in the document render at
font-weight: 400; Word shows all ten bold.

Steps to reproduce

Any Hebrew .docx whose headings were bolded in Word reproduces it. Smallest recipe:

  1. In Word, type a Hebrew line and apply Heading 2.
  2. With the (Hebrew-only) selection active, press Ctrl+B. Word writes <w:bCs/> into
    the style with no <w:b/>.
  3. Save and open the file in SuperDoc.

Word shows the heading bold; SuperDoc shows it at normal weight.

Measured in Chrome with getComputedStyle on the run element inside
.superdoc-line:

font-weight
the document as-is 400 on all ten headings
the same document with <w:b/> completed next to each <w:bCs/> 700 on all ten

The same happens for w:iCs (italic).

I have not attached the document itself because it is someone's private study
material. If a sample is needed I can produce a synthetic one — but any Hebrew Word
document with a bolded heading has the same shape.

SuperDoc version

2.10.0 (@superdoc/docx-engine 0.9.0). Also present in main at
bc4f198 / 7a655d9, and in the 2.11.0-next.9 prerelease.

Browser

Chrome

Additional context

The complex-script formatting stack looks unimplemented rather than mis-parsed.
w:bCs is parsed and preserved — RunProperties.boldCs arrives populated, and the
exporter writes it back — but normalizeRunAttrsFromOoxml
(packages/layout-engine/style-engine/src/normalize/run-attrs.ts) reads only the
Latin variants, and the layout contract downstream carries a single bold.

packages/layout-engine/contracts/src/direction-context.ts describes this as
outstanding work:

Per ECMA Annex I, when w:rtl is set or w:cs is set, the run's formatting comes from
the complex-script variants (bCs, iCs, szCs, rFonts/@cs). Otherwise it comes from
the Latin variants. […] This context is preservation-only in Wave 1a. Wave 1b
implements the stack-selection logic (resolveRunScriptContext returns whether to
render with the CS or Latin stack).

resolveRunScriptContext does not exist in the tree.

w:szCs and w:rFonts/@cs are the other two members of the same stack and are
equally unread, so a Hebrew document whose heading size comes from w:szCs should
be wrong in the same way. I have not measured that.

PR #3958 covers the two toggles (w:bCs, w:iCs).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions