Files
Chaim bfec8bdaa3
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 6s
Add dafna-decision-template skill — knowledge for template-based DOCX export
Documents the rules and decisions behind building DOCX files from דפנה's
decision template (טיוטת החלטה.dotx). The implementation lives in
mcp-server/src/legal_mcp/services/analysis_docx_exporter.py; this skill
captures the "why" so future improvements don't need to rediscover it.

Contents:
  SKILL.md                       5 critical rules, style mapping table,
                                 export flow, line classification,
                                 dash policy, placeholder handling,
                                 troubleshooting, future TODOs
  references/dotx-to-docx.md     why python-docx can't open .dotx +
                                 the conversion recipe
  references/rtl-runs.md         why <w:rtl/> is required on every run
                                 (otherwise Hebrew falls back to
                                 Times New Roman)
  references/style-mapping.md    XML dump of every template style,
                                 with the Title-via-theme gotcha
  references/line-classification.md  the 7 regex categories in
                                 _classify_line() with real examples

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 18:57:57 +00:00

5.4 KiB
Raw Permalink Blame History

מיפוי סגנונות — טיוטת החלטה.dotx

מבוסס על ניתוח word/styles.xml של הטמפלט. כל הגדרות מצוטטות מה-XML המקורי.

סגנונות בסיסיים (Word-idioms)

Normal (styleId: a1)

ברירת המחדל לפסקאות רגילות. כל שאר הסגנונות יורשים ממנו (basedOn="a1").

<rPr>
  <rFonts ascii="Times New Roman" hAnsi="Times New Roman" cs="David"/>
  <sz val="26"/>   <!-- 13pt -->
  <szCs val="26"/>
</rPr>
<pPr>
  <bidi/>                                   <!-- RTL -->
  <spacing before="120" after="120" line="360" lineRule="auto"/>
  <ind left="-454"/>                        <!-- negative left indent -->
  <jc val="both"/>                          <!-- justify -->
</pPr>

מה זה אומר לך:

  • עברית תצא ב-David 13pt (דרך cs)
  • לטינית תצא ב-Times New Roman 13pt (דרך ascii)
  • יישור justify (דו-צדדי), RTL
  • מרווח 1.5 שורות (line=360 = 1.5 × 240)

Heading 1 (styleId: 10, name: heading 1)

לכותרת ראשית (כמו "ניתוח משפטי וכתיבת עמדה בערר X").

<basedOn val="a1"/>     <!-- יורש מ-Normal → cs="David" -->
<rPr><rFonts asciiTheme="majorHAnsi" .../><sz val="40"/></rPr>  <!-- 20pt -->

Heading 1 אינו מציין cs fonts מפורשות, אבל יורש cs="David" מ-Normal. זה מבדיל אותו מ-Title, שמפנה ל-theme ריק.

Heading 2 (styleId: 2)

לכותרות מקטעים ותת-מקטעים.

<basedOn val="a1"/>
<pPr><keepNext/><spacing before="160"/><ind left="-567"/></pPr>
<rPr><b/><bCs/><u val="single"/></rPr>   <!-- bold + underline -->

Title (styleId: a5) — ⚠️ הימנע

<rPr><rFonts asciiTheme="majorHAnsi" cstheme="majorBidi" .../></rPr>

מפנה ל-theme. ב-theme1.xml: majorFont.cs = "" (ריק). → עברית נופלת ל-majorFont.latin = "Aptos Display". השתמש ב-Heading 1 במקום.

Subtitle (styleId: a7) — ⚠️ אותה בעיה של Title

לא בשימוש.

סגנונות תוכן

Quote (styleId: a9)

<basedOn val="a1"/>
<pPr><spacing before="0" after="0" line="276"/>
     <ind left="680" right="170"/></pPr>   <!-- הזחה דו-צדדית -->
<rPr><b/><bCs/></rPr>                      <!-- bold -->

לציטוטי פסיקה. הזחה פנימה, bold.

List Paragraph (styleId: a0)

<basedOn val="a1"/>
<pPr>
  <numPr><numId val="1"/></numPr>          <!-- auto-numbering -->
  <spacing after="0"/>
  <ind left="-125" hanging="357"/>
</pPr>
<rPr><rFonts ascii="David" hAnsi="David"/><sz val="28"/></rPr>  <!-- 14pt -->

numId=1 מפנה ל-abstractNumId=16, שמוגדר כ-decimal עם lvlText="%1.". כלומר Word יוסיף "1.", "2.", "3." אוטומטית לפני הטקסט.

חשוב: List Paragraph הוא היחיד בטמפלט עם numbering אוטומטי. אין bullet style מוכן. לרשימות עם (א)(ב), הסר את ה-numPr ברמת הפסקה:

from docx.oxml.ns import qn

def _strip_numpr(paragraph):
    pPr = paragraph._p.get_or_add_pPr()
    for numPr in pPr.findall(qn("w:numPr")):
        pPr.remove(numPr)

סגנונות נוספים בטמפלט (לא בשימוש כרגע)

styleId שם מה
P00, P11, P22 תבניות מותאמות אישית ישן, נראה שלא בשימוש פעיל
12, 21, 31 פיסקת רשימה 1/2/3 ללא numPr — שימוש ויזואלי בלבד
- פיסקת רשימה - ללא מספור מיועד ל-bullets ללא מספור
14 ציטוט1 וריאציה ישנה של Quote
af2 / af4 header / footer לכותרות עליונות/תחתונות

theme (word/theme/theme1.xml)

<majorFont>
  <latin typeface="Aptos Display"/>
  <cs typeface=""/>                  <!-- ריק! -->
</majorFont>
<minorFont>
  <latin typeface="Aptos"/>
  <cs typeface=""/>                  <!-- ריק! -->
</minorFont>

ה-cs ריק ב-theme — זו הסיבה ש-Title (שמפנה ל-theme) לא עובד לעברית. אל תסמוך על theme; השתמש ב-styles שמגדירים cs מפורש (Normal + כל מה שיורש ממנו).

numbering definitions

word/numbering.xml כולל ~22 abstractNum מוגדרים. הרלוונטי לנו:

numId=1 → abstractNumId=16 → numFmt=decimal, lvlText="%1."

יש גם hebrew1 (numFmt=hebrew1 = א., ב., ג.) ב-abstractNumId=0, 1. אף סגנון מוכן לא מפנה אליהם. אם תרצה בעתיד רשימה ממוספרת בעברית עם Word auto-numbering — יש להזריק numPr ידנית עם numId=29 (שמפנה ל-abstractNumId=0).

גדלים — רפרנס מהיר

style ascii cs (עברית)
Normal 13pt 13pt
Heading 1 20pt 18pt
Heading 2 13pt (ירושה) + bold + underline אותו דבר
Title 28pt (Aptos Display — לא עברית!)
List Paragraph 14pt (David) 14pt
Quote 13pt (ירושה) + bold 13pt

טיפ

כדי לבדוק את כל הסגנונות שבמסמך:

from docx import Document
d = Document("skills/docx/decision_template.docx")
for s in sorted(d.styles, key=lambda x: x.name):
    print(s.type, s.name, s.style_id)