---
name: legal-docx
description: >
יצירת מסמכים משפטיים בעברית בפורמט DOCX עם תמיכה מלאה ב-RTL, עקוב אחר שינויים,
והערות. משתמש בסקיל הבסיסי docx ומוסיף התמחות בתחום המשפטי הישראלי.
טריגרים: "מסמך משפטי", "הסכם", "כתב הגנה", "כתב תביעה", "בקשה", "תצהיר",
"מכתב התראה", "חוזה", "הסכם שירותים", "ייפוי כוח", "פרוטוקול", "החלטה",
"צו", "פסק דין", "כתב טענות", בקשה ליצור מסמך DOCX בעברית, מסמך RTL,
"tracked changes בעברית", "הערות שוליים משפטיות", "עקוב אחר שינויים".
גם מתאים כאשר המשתמש מבקש מסמך Word בעברית עם פונט David/FrankRuehl/Miriam,
שוליים 2.5 ס"מ, או כל מסמך מקצועי בעברית שדורש עיצוב משפטי מדויק.
פיצ'רים: טבלאות RTL, הערות שוליים, תוכן עניינים, היפרלינקים,
לוגו/נייר פירמה, עריכת DOCX קיים, tracked changes, comments,
מרווח שורות, קו תחתי, מספר סקשנים, זיהוי אוטומטי של סוג מסמך.
---
# Legal DOCX v3.0 — מסמכים משפטיים בעברית
סקיל זה מרחיב את סקיל docx הבסיסי עם התמחות במסמכים משפטיים ישראליים.
**תמיד לקרוא קודם** את `/mnt/skills/public/docx/SKILL.md` — הסקיל הזה מניח שאתה מכיר את תהליך העבודה הבסיסי (docx-js, unpack/pack, tracked changes, comments).
---
## 🔴 קריטי: כללי RTL שחייבים לזכור
### הכלל המרכזי: START/END במקום LEFT/RIGHT
**במסמך עברי עם `bidirectional: true`, לעולם אל תשתמש ב-`AlignmentType.LEFT` או `AlignmentType.RIGHT` לפסקאות ומספור!**
| רוצה יישור ל... | ❌ לא להשתמש | ✅ להשתמש |
|-----------------|-------------|----------|
| **ימין** | `LEFT` או `RIGHT` | `AlignmentType.START` |
| **שמאל** | `LEFT` או `RIGHT` | `AlignmentType.END` |
| **מרכז** | — | `AlignmentType.CENTER` |
| **שני צדדים** | — | `AlignmentType.BOTH` |
> **למה?** כש-`bidirectional: true`, Word מתבלבל עם LEFT/RIGHT. `START` = התחלה = ימין ב-RTL, `END` = סוף = שמאל ב-RTL.
### שלוש הגדרות RTL חובה
כל מסמך עברי חייב את **שלושת** ההגדרות הבאות בכל הרמות:
```javascript
// 1. ברמת ה-Section
sections: [{
properties: {
bidi: true // ← חובה!
}
}]
// 2. ברמת כל Paragraph
new Paragraph({
bidirectional: true, // ← חובה!
alignment: AlignmentType.BOTH, // או START/CENTER/END
})
// 3. ברמת כל TextRun
new TextRun({
text: "טקסט בעברית",
rightToLeft: true, // ← חובה!
font: "David",
})
```
**חוסר באחת מהן = יישור שגוי או טקסט הפוך!**
---
## זיהוי סוג מסמך — Document Type Detection
**לפני יצירת מסמך, זהה את סוגו.** לכל סוג יש מבנה שונה:
| סוג מסמך | דוגמאות | Header בית משפט? | מבנה מיוחד |
|----------|---------|------------------|------------|
| **כתב טענות** | תביעה, הגנה, בקשה, ערעור, תצהיר, בר"ע | ✅ כן | טבלת Header עם בית משפט + מספר תיק |
| **מכתב התראה** | התראה, דרישה, מכתב עו"ד | ❌ לא | לוגו/פרטי משרד, "הנדון:", חתימה |
| **הסכם/חוזה** | הסכם שירותים, NDA, חוזה שכירות | ❌ לא | הואילים, צדדים, חתימות בשני טורים |
| **מסמך כללי** | חוות דעת, מזכר, סיכום | ❌ לא | לפי הצורך |
### טריגרים לזיהוי
```
כתב טענות ← "בית משפט", "בית הדין", "תביעה", "הגנה", "בקשה",
"ערעור", "תצהיר", "המבקש", "המשיב", "התובע", "הנתבע", "בר\"ע"
מכתב התראה ← "התראה", "דרישה", "לכבוד", "הנדון:", "נשלח מבלי לפגוע"
הסכם/חוזה ← "הסכם", "חוזה", "בין:", "לבין:", "הואיל", "צד א'", "צד ב'",
"ולראיה באו הצדדים"
```
---
## פונטים ומידות
### פונטים משפטיים
| פונט | שימוש | size (half-points) |
|------|-------|-------------------|
| **David** | ברירת מחדל, גוף טקסט | 24 (12pt) |
| **FrankRuehl** | פורמלי/שמרני | 24 (12pt) |
| **Miriam** | מודרני יותר | 24 (12pt) |
**חשוב:** תמיד להגדיר גם `w:cs` (Complex Script) וגם `w:ascii`/`w:hAnsi`:
```javascript
new TextRun({ text: "...", font: "David", rightToLeft: true })
// docx-js מייצר:
```
### מידות ושוליים
```
2.5 ס"מ = 1417 DXA (ברירת מחדל משפטי)
3.0 ס"מ = 1701 DXA
2.0 ס"מ = 1134 DXA
1.0 אינץ' = 1440 DXA
A4 = 11906 × 16838 DXA
רוחב תוכן (A4, שוליים 2.5 ס"מ) = 9072 DXA
רוחב תוכן (A4, שוליים 2.0 ס"מ) = 9638 DXA
```
---
## מספור סעיפים משפטיים
**⚠️ שים לב: `alignment: AlignmentType.START` — לא LEFT ולא RIGHT!**
```javascript
numbering: {
config: [{
reference: "legal-clauses",
levels: [
{
level: 0,
format: LevelFormat.DECIMAL,
text: "%1.",
alignment: AlignmentType.START, // ✅ START — לא RIGHT!
suffix: "tab",
style: { paragraph: { indent: { left: 720, hanging: 360 } } }
},
{
level: 1,
format: LevelFormat.DECIMAL,
text: "%1.%2",
alignment: AlignmentType.START, // ✅ START — לא RIGHT!
suffix: "tab",
style: { paragraph: { indent: { left: 1440, hanging: 500 } } }
},
{
level: 2,
format: LevelFormat.DECIMAL,
text: "%1.%2.%3",
alignment: AlignmentType.START, // ✅ START
suffix: "tab",
style: { paragraph: { indent: { left: 2160, hanging: 640 } } }
}
]
}]
}
```
**שימוש:**
```javascript
new Paragraph({
bidirectional: true,
numbering: { reference: "legal-clauses", level: 0 },
children: [new TextRun({ text: "תוכן הסעיף", font: "David", size: 24, rightToLeft: true })]
})
```
> **הבעיה שנפתרה:** בלי `AlignmentType.START`, המספור מופיע כ-".1" במקום "1."
---
## טבלאות RTL
**⚠️ קריטי: `visuallyRightToLeft: true` — בלי זה העמודות יהיו הפוכות!**
```javascript
const { Table, TableRow, TableCell, BorderStyle, WidthType, ShadingType } = require('docx');
const CONTENT_WIDTH = 9072; // A4 עם שוליים 2.5 ס"מ (11906 - 1417×2)
const border = { style: BorderStyle.SINGLE, size: 1, color: "999999" };
const borders = { top: border, bottom: border, left: border, right: border };
const noBorders = {
top: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
bottom: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
left: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" },
right: { style: BorderStyle.NONE, size: 0, color: "FFFFFF" }
};
// Helper function לתאים בעברית
const rtlCell = (text, width, opts = {}) => new TableCell({
borders: opts.noBorders ? noBorders : borders,
width: { size: width, type: WidthType.DXA },
margins: { top: 80, bottom: 80, left: 120, right: 120 },
...(opts.shading ? { shading: { fill: opts.shading, type: ShadingType.CLEAR } } : {}),
children: [new Paragraph({
bidirectional: true,
alignment: opts.alignment || AlignmentType.CENTER,
children: [new TextRun({
text, font: "David", size: 24, rightToLeft: true, bold: opts.bold
})]
})]
});
// טבלה עם גבולות
new Table({
visuallyRightToLeft: true, // ✅ קריטי! בלי זה העמודות הפוכות
width: { size: CONTENT_WIDTH, type: WidthType.DXA },
columnWidths: [4536, 2268, 2268], // חייב להסתכם ל-CONTENT_WIDTH
rows: [
new TableRow({ children: [
rtlCell("סוג שירות", 4536, { bold: true, shading: "D5E8F0" }),
rtlCell("תעריף", 2268, { bold: true, shading: "D5E8F0" }),
rtlCell("הערות", 2268, { bold: true, shading: "D5E8F0" }),
]}),
new TableRow({ children: [
rtlCell("ייעוץ משפטי", 4536),
rtlCell("850 ש״ח", 2268),
rtlCell("בתוספת מע״מ", 2268),
]}),
]
})
// טבלה ללא גבולות (לחתימות / header)
new Table({
visuallyRightToLeft: true,
width: { size: CONTENT_WIDTH, type: WidthType.DXA },
columnWidths: [CONTENT_WIDTH / 2, CONTENT_WIDTH / 2],
rows: [
new TableRow({ children: [
rtlCell("חתימה: ________", CONTENT_WIDTH / 2, { noBorders: true, alignment: AlignmentType.CENTER }),
rtlCell("חתימה: ________", CONTENT_WIDTH / 2, { noBorders: true, alignment: AlignmentType.CENTER }),
]})
]
})
```
**כללים:**
- **`visuallyRightToLeft: true`** — חובה! בלי זה העמודות משמאל לימין
- **`WidthType.DXA`** — לא PERCENTAGE (פחות אמין ב-RTL)
- **`columnWidths`** — סכום חייב להיות שווה ל-`CONTENT_WIDTH`
- **`bidirectional: true` + `rightToLeft: true`** — בכל תא
---
## Tracked Changes — עקוב אחר שינויים
### שם מחבר בעברית
```xml
```
### שינוי ערך (סכום, תאריך, תקופה)
פצל את הטקסט ועטוף רק את הערך שמשתנה:
```xml
...RTL PROPS...
שכר הטרחה יעמוד על סך של
...RTL PROPS...750
...RTL PROPS...850
...RTL PROPS...
ש״ח לשעת עבודה
```
### מחיקת סעיף שלם
סמן גם את ה-paragraph mark כ-deleted:
```xml
...RTL PROPS...
הסעיף שנמחק
```
### RTL PROPS — בלוק rPr מלא לכל run
```xml
```
### קבלה/דחייה של שינויים
**קבלת Insertion:**
```
לפני: ...טקסט חדש
אחרי: ...טקסט חדש
→ הסר את תגית ושמור את התוכן הפנימי.
```
**דחיית Insertion:**
```
לפני: ...טקסט חדש
אחרי: (הסר לחלוטין)
→ מחק את כל בלוק ה- כולל תוכנו.
```
**קבלת מחיקה:**
```
לפני: ...טקסט שנמחק
אחרי: (הסר לחלוטין)
→ מחק את כל בלוק ה- כולל תוכנו — המחיקה מתקבלת.
```
**שחזור טקסט מקורי (דחיית מחיקה):**
```
לפני: ...טקסט מקורי
אחרי: ...טקסט מקורי
→ הסר , החלף ב-, הסר מ-rPr אם קיים.
```
---
## הערות (Comments)
הערות משמשות בסקירה משפטית להסביר *למה* בוצע שינוי:
```bash
python /mnt/skills/public/docx/scripts/comment.py unpacked/ 0 "הערה בעברית" --author "עו״ד כהן"
```
שימושים נפוצים:
- הסבר לשינוי סכום או תאריך
- דגל על סעיף בעייתי
- הפניה לפסיקה או חקיקה
- שאלה ללקוח / לצד השני
> **הערה:** `comment.py` מטפל אוטומטית ב-Content_Types ו-relationships.
---
## עריכת DOCX קיים (Unpack → Edit → Pack)
### תהליך מאומת
```bash
# 1. פתיחת הקובץ
python /mnt/skills/public/docx/scripts/unpack.py input.docx unpacked/
# 2. עריכת word/document.xml (או קבצי XML אחרים)
# 3. ארגון מחדש
python /mnt/skills/public/docx/scripts/pack.py unpacked/ output.docx --original input.docx
```
### מיקום הוספת תוכן — כלל קריטי
```
⚠️ פסקאות חדשות חייבות להיכנס *לפני* האחרון בגוף המסמך.
הוספה *אחרי* sectPr תיכשל בוולידציה.
מבנה תקין:
... ← פסקאות קיימות
... ← פסקה חדשה כאן ✅
... ← תמיד אחרון
```
### דוגמה — הוספת פסקה בעברית
```xml
הטקסט החדש
```
---
## הערות שוליים (Footnotes)
**השימוש המרכזי:** הפניות לחקיקה ופסיקה.
```javascript
const { FootnoteReferenceRun } = require('docx');
// 1. הגדרה ב-Document:
const doc = new Document({
footnotes: {
1: { children: [new Paragraph({
bidirectional: true, alignment: AlignmentType.START, // ✅ START
children: [new TextRun({
text: "חוק החוזים (חלק כללי), התשל״ג-1973, סעיף 12.",
font: "David", size: 20, rightToLeft: true // 10pt להערות שוליים
})]
})] },
2: { children: [new Paragraph({
bidirectional: true, alignment: AlignmentType.START,
children: [new TextRun({
text: "ע״א 1234/20 כהן נ׳ לוי, פסקה 15 (פורסם בנבו, 1.1.2024).",
font: "David", size: 20, rightToLeft: true
})]
})] },
},
// ...sections
});
// 2. הפניה בגוף הטקסט:
new Paragraph({
bidirectional: true, alignment: AlignmentType.BOTH,
children: [
new TextRun({ text: "חובת תום הלב", font: "David", size: 24, rightToLeft: true }),
new FootnoteReferenceRun(1),
new TextRun({ text: " חלה על כל שלבי המשא ומתן", font: "David", size: 24, rightToLeft: true }),
new FootnoteReferenceRun(2),
new TextRun({ text: ".", font: "David", size: 24, rightToLeft: true }),
]
})
```
### תיקון RTL בהערות שוליים (post-unpack)
docx-js לא מגדיר RTL מלא בהערות שוליים. אחרי unpack, צריך לתקן ב-`word/footnotes.xml`:
```xml
...
```
---
## מרווח שורות (Line Spacing)
**דרישת בתי המשפט:** בדרך כלל 1.5 שורות.
```javascript
const { LineRuleType } = require('docx');
// LineRuleType.AUTO — הערך הוא ב-1/240 שורה
spacing: { line: 240, lineRule: LineRuleType.AUTO } // 1.0 — צפוף
spacing: { line: 276, lineRule: LineRuleType.AUTO } // 1.15 — ברירת מחדל Word
spacing: { line: 360, lineRule: LineRuleType.AUTO } // 1.5 — נדרש בבתי משפט
spacing: { line: 480, lineRule: LineRuleType.AUTO } // 2.0 — כפול
// שילוב עם before/after:
spacing: { line: 360, lineRule: LineRuleType.AUTO, before: 120, after: 120 }
```
---
## תוכן עניינים (TOC)
**⚠️ חובה: TOC ידני (לא TableOfContents).**
`TableOfContents` של docx-js מייצר שדה שוורד מעדכן ב-F9 ומאבד הגדרות RTL.
```javascript
const { Tab, TabStopType, LeaderType, PageBreak } = require('docx');
// שורת TOC ידנית
const tocEntry = (text, pageNum, opts = {}) => new Paragraph({
bidirectional: true,
spacing: { after: 60, line: 276, lineRule: LineRuleType.AUTO },
...(opts.indent ? { indent: { right: opts.indent } } : {}),
tabStops: [{ type: TabStopType.RIGHT, position: 9026, leader: LeaderType.DOT }],
children: [
new TextRun({
text, font: "David", size: 24, rightToLeft: true,
bold: opts.bold || false,
}),
new TextRun({ children: [new Tab()], font: "David", rightToLeft: true }),
new TextRun({
text: String(pageNum), font: "David", size: 24, rightToLeft: true,
}),
]
});
// שימוש:
new Paragraph({
bidirectional: true, alignment: AlignmentType.CENTER,
spacing: { after: 200 },
children: [new TextRun({
text: "תוכן עניינים", font: "David", size: 32, bold: true, rightToLeft: true
})]
}),
tocEntry("פרק א׳ — הגדרות כלליות", 2, { bold: true }),
tocEntry("1. הגדרות יסוד", 2, { indent: 400 }),
tocEntry("פרק ב׳ — השירותים", 3, { bold: true }),
new Paragraph({ children: [new PageBreak()] }),
```
---
## קו תחתי (Underline)
```javascript
const { UnderlineType } = require('docx');
// קו תחתי רגיל:
new TextRun({
text: "נושא: הסכם שירותים",
font: "David", size: 24, rightToLeft: true,
underline: { type: UnderlineType.SINGLE }
})
// קו תחתי כפול (לכותרות חשובות):
underline: { type: UnderlineType.DOUBLE }
// סוגים שימושיים: SINGLE, DOUBLE, THICK, DOTTED, DASH, WAVE
```
---
## מספר סקשנים (Multiple Sections)
**שימוש:** כותרות שונות לנספחים, עמוד לרוחב לטבלאות, שוליים שונים.
```javascript
const doc = new Document({
sections: [
// סקשן 1 — גוף ההסכם
{
properties: {
page: { size: { width: 11906, height: 16838 },
margin: { top: 1417, right: 1417, bottom: 1417, left: 1417 } },
bidi: true,
},
headers: {
default: new Header({ children: [new Paragraph({
bidirectional: true, alignment: AlignmentType.CENTER,
children: [new TextRun({ text: "הסכם שירותים", font: "David", size: 20, bold: true, rightToLeft: true })]
})] })
},
children: [ /* ... */ ]
},
// סקשן 2 — נספח עם כותרת שונה
{
properties: {
page: { size: { width: 11906, height: 16838 },
margin: { top: 1417, right: 1417, bottom: 1417, left: 1417 } },
bidi: true,
},
headers: {
default: new Header({ children: [new Paragraph({
bidirectional: true, alignment: AlignmentType.START, // ✅ START
children: [new TextRun({ text: "נספח א׳ — לוח תעריפים", font: "David", size: 20, bold: true, rightToLeft: true })]
})] })
},
children: [ /* ... */ ]
}
]
});
```
---
## לוגו/תמונה בכותרת (Letterhead)
```javascript
const { ImageRun } = require('docx');
const logoBuffer = fs.readFileSync('/path/to/logo.png');
headers: {
default: new Header({
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
children: [
new ImageRun({
data: logoBuffer,
transformation: { width: 200, height: 60 }, // pixels
type: "png",
}),
],
}),
new Paragraph({
bidirectional: true, alignment: AlignmentType.CENTER,
children: [new TextRun({
text: "משרד עורכי דין ישראלי ושות׳",
font: "David", size: 20, bold: true, rightToLeft: true
})],
}),
],
}),
}
```
**הערה:** תמונה חייבת להיות קובץ אמיתי — לבקש מהמשתמש אם אין.
---
## היפרלינקים
```javascript
const { ExternalHyperlink, UnderlineType } = require('docx');
new Paragraph({
bidirectional: true,
children: [
new TextRun({ text: "ראה: ", font: "David", size: 24, rightToLeft: true }),
new ExternalHyperlink({
link: "https://www.nevo.co.il/law_html/law01/073_002.htm",
children: [new TextRun({
text: "חוק החוזים באתר נבו",
font: "David", size: 24, rightToLeft: true,
color: "0563C1",
underline: { type: UnderlineType.SINGLE },
})],
}),
]
})
```
**⚠️ אזהרות:**
- **לא להשתמש ב-`style: "Hyperlink"`** — מפריע ל-RTL!
- **לא להוסיף `alignment: AlignmentType.RIGHT`** — `bidirectional: true` מספיק
---
## תבניות מסמכים — Document Templates
### תבנית 1: כתב טענות (בקשה, תביעה, הגנה, ערעור)
```javascript
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
AlignmentType, LevelFormat, BorderStyle, WidthType } = require('docx');
const PAGE_WIDTH = 11906;
const MARGINS = { top: 1134, right: 1134, bottom: 1134, left: 1134 };
const CONTENT_WIDTH = PAGE_WIDTH - MARGINS.left - MARGINS.right;
const noBorder = { style: BorderStyle.NONE, size: 0, color: "FFFFFF" };
const noBorders = { top: noBorder, bottom: noBorder, left: noBorder, right: noBorder };
// Header בית משפט — טבלה עם שם בית המשפט (ימין) ומספר תיק (שמאל)
function courtHeader(courtName, caseNumber) {
return new Table({
width: { size: CONTENT_WIDTH, type: WidthType.DXA },
columnWidths: [CONTENT_WIDTH / 2, CONTENT_WIDTH / 2],
visuallyRightToLeft: true,
rows: [
new TableRow({
children: [
new TableCell({
width: { size: CONTENT_WIDTH / 2, type: WidthType.DXA },
borders: noBorders,
children: [new Paragraph({
bidirectional: true, alignment: AlignmentType.START,
children: [new TextRun({ text: courtName, bold: true, font: "David", size: 26, rightToLeft: true })]
})]
}),
new TableCell({
width: { size: CONTENT_WIDTH / 2, type: WidthType.DXA },
borders: noBorders,
children: [new Paragraph({
bidirectional: true, alignment: AlignmentType.END,
children: [new TextRun({ text: caseNumber, bold: true, font: "David", size: 26, rightToLeft: true })]
})]
})
]
})
]
});
}
// כותרת ראשית ממורכזת עם קו תחתון
function mainTitle(text) {
return new Paragraph({
bidirectional: true, alignment: AlignmentType.CENTER,
spacing: { before: 300, after: 300 },
children: [new TextRun({ text, bold: true, font: "David", size: 28, rightToLeft: true, underline: {} })]
});
}
// כותרת משנה מיושרת לימין עם קו תחתון
function subHeading(text) {
return new Paragraph({
bidirectional: true, alignment: AlignmentType.START,
spacing: { before: 240, after: 120 },
children: [new TextRun({ text, bold: true, font: "David", size: 24, rightToLeft: true, underline: {} })]
});
}
// שימוש:
const doc = new Document({
numbering: {
config: [{
reference: "legal-clauses",
levels: [{
level: 0, format: LevelFormat.DECIMAL, text: "%1.",
alignment: AlignmentType.START, suffix: "tab",
style: { paragraph: { indent: { left: 360, hanging: 360 } } }
}]
}]
},
sections: [{
properties: {
page: { size: { width: PAGE_WIDTH, height: 16838 }, margin: MARGINS },
bidi: true
},
children: [
courtHeader("בית המשפט המחוזי בתל אביב", "ת\"א 12345-01-26"),
mainTitle("כתב תביעה"),
// ... פרטי צדדים, סעיפים, חתימה
]
}]
});
```
### תבנית 2: מכתב התראה
```javascript
// מכתב התראה — ללא header בית משפט, עם פרטי משרד
function letterHeader(firmName, address, phone, email) {
return [
new Paragraph({
bidirectional: true, alignment: AlignmentType.START,
children: [new TextRun({ text: firmName, bold: true, font: "David", size: 28, rightToLeft: true })]
}),
new Paragraph({
bidirectional: true, alignment: AlignmentType.START,
children: [new TextRun({ text: address, font: "David", size: 22, rightToLeft: true })]
}),
new Paragraph({
bidirectional: true, alignment: AlignmentType.START,
spacing: { after: 300 },
children: [new TextRun({ text: `טל': ${phone} | ${email}`, font: "David", size: 22, rightToLeft: true })]
}),
];
}
function subjectLine(text) {
return new Paragraph({
bidirectional: true, alignment: AlignmentType.CENTER,
spacing: { before: 200, after: 200 },
children: [
new TextRun({ text: "הנדון: ", bold: true, font: "David", size: 24, rightToLeft: true }),
new TextRun({ text, bold: true, font: "David", size: 24, rightToLeft: true, underline: {} })
]
});
}
// שימוש:
sections: [{
properties: { page: { ... }, bidi: true },
children: [
...letterHeader("משרד עו\"ד כהן ושות'", "רח' הרצל 1, תל אביב", "03-1234567", "office@cohen-law.co.il"),
new Paragraph({
bidirectional: true, alignment: AlignmentType.START,
children: [new TextRun({ text: "תאריך: 10.2.2026", font: "David", size: 24, rightToLeft: true })]
}),
new Paragraph({
bidirectional: true, alignment: AlignmentType.START,
spacing: { before: 200 },
children: [new TextRun({ text: "לכבוד: [שם הנמען]", font: "David", size: 24, rightToLeft: true })]
}),
subjectLine("התראה בטרם נקיטת הליכים משפטיים"),
// ... גוף המכתב
]
}]
```
### תבנית 3: הסכם/חוזה
```javascript
// הסכם — הואילים, צדדים, חתימות בשני טורים
function contractTitle(text) {
return new Paragraph({
bidirectional: true, alignment: AlignmentType.CENTER,
spacing: { after: 300 },
children: [new TextRun({ text, bold: true, font: "David", size: 32, rightToLeft: true })]
});
}
function partyClause(label, name, id, address, alias) {
return new Paragraph({
bidirectional: true, alignment: AlignmentType.BOTH,
spacing: { after: 120 },
children: [
new TextRun({ text: `${label}: `, bold: true, font: "David", size: 24, rightToLeft: true }),
new TextRun({ text: `${name}, ח.פ./ת.ז. ${id}, מ${address} (להלן: "`, font: "David", size: 24, rightToLeft: true }),
new TextRun({ text: alias, bold: true, font: "David", size: 24, rightToLeft: true }),
new TextRun({ text: '")', font: "David", size: 24, rightToLeft: true }),
]
});
}
function signatureTable() {
return new Table({
width: { size: CONTENT_WIDTH, type: WidthType.DXA },
columnWidths: [CONTENT_WIDTH / 2, CONTENT_WIDTH / 2],
visuallyRightToLeft: true,
rows: [
new TableRow({
children: [
new TableCell({
borders: noBorders,
children: [
new Paragraph({ bidirectional: true, alignment: AlignmentType.CENTER,
children: [new TextRun({ text: "_________________", font: "David", size: 24, rightToLeft: true })] }),
new Paragraph({ bidirectional: true, alignment: AlignmentType.CENTER,
children: [new TextRun({ text: "צד א'", font: "David", size: 24, rightToLeft: true })] })
]
}),
new TableCell({
borders: noBorders,
children: [
new Paragraph({ bidirectional: true, alignment: AlignmentType.CENTER,
children: [new TextRun({ text: "_________________", font: "David", size: 24, rightToLeft: true })] }),
new Paragraph({ bidirectional: true, alignment: AlignmentType.CENTER,
children: [new TextRun({ text: "צד ב'", font: "David", size: 24, rightToLeft: true })] })
]
})
]
})
]
});
}
// שימוש:
sections: [{
properties: { page: { ... }, bidi: true },
children: [
contractTitle("הסכם שירותים"),
new Paragraph({
bidirectional: true, alignment: AlignmentType.CENTER,
children: [new TextRun({ text: "נערך ונחתם בתל אביב ביום __________", font: "David", size: 24, rightToLeft: true })]
}),
partyClause("מצד אחד", "[שם]", "[מספר]", "[כתובת]", "המזמין"),
partyClause("מצד שני", "[שם]", "[מספר]", "[כתובת]", "הספק"),
// הואילים...
// סעיפים...
new Paragraph({
bidirectional: true, alignment: AlignmentType.CENTER,
spacing: { before: 400, after: 300 },
children: [new TextRun({ text: "ולראיה באו הצדדים על החתום:", bold: true, font: "David", size: 24, rightToLeft: true })]
}),
signatureTable()
]
}]
```
---
## Quick Reference — טבלת עזר מהיר
### יישור
| רוצה | השתמש ב... | ❌ לא להשתמש |
|------|-----------|-------------|
| ימין | `AlignmentType.START` | `LEFT`, `RIGHT` |
| שמאל | `AlignmentType.END` | `LEFT`, `RIGHT` |
| מרכז | `AlignmentType.CENTER` | — |
| שני צדדים | `AlignmentType.BOTH` | `JUSTIFIED` |
### גדלי טקסט (half-points)
| שימוש | size | נקודות |
|-------|------|--------|
| גוף טקסט | 24 | 12pt |
| כותרת משנה | 26 | 13pt |
| כותרת ראשית | 28-32 | 14-16pt |
| הערות שוליים | 20 | 10pt |
| Header/Footer | 18-20 | 9-10pt |
### מרווחי שורות
| רווח | line value |
|------|-----------|
| 1.0 | 240 |
| 1.15 | 276 |
| 1.5 | 360 |
| 2.0 | 480 |
### Checklist — הגדרות חובה
```
☐ Section: bidi: true
☐ Paragraph: bidirectional: true
☐ TextRun: rightToLeft: true
☐ Numbering: alignment: AlignmentType.START
☐ Table: visuallyRightToLeft: true
☐ Footnotes: alignment: AlignmentType.START
```
---
## 🔧 Troubleshooting
**מספור מופיע הפוך (.1 במקום 1.):**
→ וודא `alignment: AlignmentType.START` במספור (לא RIGHT!)
**טקסט מופיע משמאל לימין:**
→ וודא את שלושת ההגדרות: Section `bidi`, Paragraph `bidirectional`, TextRun `rightToLeft`
**עמודות טבלה הפוכות:**
→ הוסף `visuallyRightToLeft: true` לטבלה
**columnWidths לא מסתכם:**
→ וודא שסכום כל הרוחבים = CONTENT_WIDTH (9072 לשוליים 2.5 ס"מ, חישוב: 11906 - 1417×2)
**המסמך לא נפתח / שגיאה ב-Word:**
→ בדוק שלא הוספת פסקה אחרי `` (חייב להיות אחרון ב-body)
→ וודא `npm list docx` >= 8.0.0
**הערות שוליים לא ב-RTL:**
→ אחרי unpack, תקן ידנית ב-word/footnotes.xml (ראה סעיף הערות שוליים)
---
## טעויות נפוצות — Common Pitfalls
| ❌ טעות | ✅ תיקון |
|--------|---------|
| `AlignmentType.RIGHT` במספור | `AlignmentType.START` |
| `AlignmentType.LEFT` ליישור שמאלי | `AlignmentType.END` |
| טבלה בלי `visuallyRightToLeft` | הוסף `visuallyRightToLeft: true` |
| שכחת `bidirectional: true` בפסקה | הוסף לכל פסקה |
| שכחת `rightToLeft: true` ב-TextRun | הוסף לכל TextRun |
| שכחת `bidi: true` ב-Section | הוסף ל-properties |
| הוספת פסקה אחרי `sectPr` | הוסף לפני `sectPr` |
| שימוש ב-`style: "Hyperlink"` | הגדר ידנית `color` + `underline` |
| `columnWidths` לא מסתכם נכון | וודא שהסכום = `CONTENT_WIDTH` |
---
## קבצי עזר
- **`references/document-types.md`** — מבנים מפורטים ל-9 סוגי מסמכים משפטיים
- **`scripts/create-legal-doc.js`** — סקריפט בסיסי עם כל הגדרות ה-RTL המתוקנות
---
## Dependencies
```bash
npm install docx
```
**גרסה מומלצת:** docx >= 8.0.0