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

Labels

status: queuedEngineering work is queued; no delivery date is committed.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions