Reorganize: skills/ directory + move memory to docs/
skill-legal-decision/ → skills/decision/ skill-legal-assistant/ → skills/assistant/ skill-legal-docx/ → skills/docx/ memory/*.md → docs/ Also removed: TASKS.md (use TaskMaster), classifier.py (replaced by local_classifier.py) Updated all references in CLAUDE.md, scripts, PRDs, docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
635
skills/decision/scripts/create-decision-structure.cjs
Normal file
635
skills/decision/scripts/create-decision-structure.cjs
Normal file
@@ -0,0 +1,635 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* create-decision-structure.js — טיוטת מבנה החלטת ועדת ערר
|
||||
*
|
||||
* מייצר קובץ DOCX מעוצב עם כל חלקי ההחלטה (בלוקים א-יב).
|
||||
* בלוקים א-ט ממולאים בתוכן, בלוק י (דיון) ויא (סיכום) = placeholders.
|
||||
*
|
||||
* שימוש:
|
||||
* node create-decision-structure.js <input.json> [output.docx]
|
||||
*
|
||||
* מבוסס על create-legal-doc.js מתוך legal-docx skill.
|
||||
* כללי RTL: START/END (לא LEFT/RIGHT), bidi+bidirectional+rightToLeft בכל רמה.
|
||||
*
|
||||
* v1.0
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const {
|
||||
Document, Packer, Paragraph, TextRun, Header, Footer,
|
||||
AlignmentType, HeadingLevel, PageNumber, LevelFormat,
|
||||
Table, TableRow, TableCell, WidthType, BorderStyle,
|
||||
ShadingType, UnderlineType
|
||||
} = require(path.join(process.cwd(), 'node_modules', 'docx'));
|
||||
|
||||
// ═══════════════════════════════════════════════
|
||||
// CONFIGURATION
|
||||
// ═══════════════════════════════════════════════
|
||||
const FONT = "David";
|
||||
const FONT_SIZE = 24; // 12pt
|
||||
const HEADING1_SIZE = 32; // 16pt — "החלטה"
|
||||
const HEADING2_SIZE = 28; // 14pt — כותרות פרקים
|
||||
const MARGIN_CM = 2.5;
|
||||
const MARGIN_DXA = Math.round(MARGIN_CM / 2.54 * 1440); // 1417
|
||||
const PAGE_WIDTH = 11906; // A4
|
||||
const PAGE_HEIGHT = 16838;
|
||||
const CONTENT_WIDTH = PAGE_WIDTH - MARGIN_DXA * 2; // 9072
|
||||
|
||||
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" }
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════
|
||||
// RTL HELPERS — מבוסס על create-legal-doc.js
|
||||
// ═══════════════════════════════════════════════
|
||||
|
||||
const rtlRun = (text, opts = {}) => new TextRun({
|
||||
text,
|
||||
font: opts.font || FONT,
|
||||
size: opts.size || FONT_SIZE,
|
||||
bold: opts.bold || false,
|
||||
underline: opts.underline ? { type: UnderlineType.SINGLE } : undefined,
|
||||
rightToLeft: true,
|
||||
});
|
||||
|
||||
const rtlPara = (children, opts = {}) => new Paragraph({
|
||||
bidirectional: true,
|
||||
alignment: opts.alignment || AlignmentType.BOTH,
|
||||
spacing: opts.spacing || { after: 120, line: 276 }, // 1.15 line spacing = 276 twips
|
||||
indent: opts.indent,
|
||||
children: Array.isArray(children) ? children : [children],
|
||||
...(opts.heading ? { heading: opts.heading } : {}),
|
||||
});
|
||||
|
||||
// כותרת ראשית — "החלטה"
|
||||
const mainTitle = (text) => rtlPara(
|
||||
rtlRun(text, { bold: true, size: HEADING1_SIZE }),
|
||||
{ heading: HeadingLevel.HEADING_1, alignment: AlignmentType.CENTER, spacing: { before: 240, after: 240 } }
|
||||
);
|
||||
|
||||
// כותרת פרק — "תמצית טענות הצדדים", "דיון והכרעה"
|
||||
const sectionTitle = (text) => rtlPara(
|
||||
rtlRun(text, { bold: true, size: HEADING2_SIZE, underline: true }),
|
||||
{ heading: HeadingLevel.HEADING_2, alignment: AlignmentType.CENTER, spacing: { before: 360, after: 240 } }
|
||||
);
|
||||
|
||||
// כותרת משנה — "טענות העוררים"
|
||||
const subTitle = (text) => rtlPara(
|
||||
rtlRun(text, { bold: true, size: FONT_SIZE }),
|
||||
{ alignment: AlignmentType.CENTER, spacing: { before: 240, after: 160 } }
|
||||
);
|
||||
|
||||
// סעיף ממוספר — מספר bold + טקסט רגיל
|
||||
const numberedPara = (num, text) => rtlPara([
|
||||
rtlRun(`${num}. `, { bold: true }),
|
||||
rtlRun(text),
|
||||
], { spacing: { after: 120, line: 276 } });
|
||||
|
||||
// ציטוט (blockquote) — הזחה משני הצדדים
|
||||
const blockquote = (text) => rtlPara(
|
||||
rtlRun(text),
|
||||
{ indent: { left: 567, right: 567 }, spacing: { before: 120, after: 120, line: 276 } }
|
||||
);
|
||||
|
||||
// תיבת תמונה — מסגרת אפורה עם הנחיה
|
||||
const imageBox = (description) => new Paragraph({
|
||||
bidirectional: true,
|
||||
alignment: AlignmentType.CENTER,
|
||||
spacing: { before: 200, after: 200 },
|
||||
shading: { type: ShadingType.CLEAR, fill: "F0F0F0" },
|
||||
children: [
|
||||
new TextRun({
|
||||
text: `📷 תמונה: ${description}`,
|
||||
font: FONT,
|
||||
size: FONT_SIZE,
|
||||
rightToLeft: true,
|
||||
bold: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
// Placeholder — טקסט אפור שמסמן מקום
|
||||
const placeholder = (text) => rtlPara(
|
||||
new TextRun({
|
||||
text: `[${text}]`,
|
||||
font: FONT,
|
||||
size: FONT_SIZE,
|
||||
rightToLeft: true,
|
||||
italics: true,
|
||||
color: "808080",
|
||||
}),
|
||||
{ alignment: AlignmentType.CENTER, spacing: { before: 200, after: 200 } }
|
||||
);
|
||||
|
||||
// רווח
|
||||
const spacer = (after = 200) => rtlPara(rtlRun(""), { spacing: { after, before: 0 } });
|
||||
|
||||
// תא בטבלה
|
||||
const rtlCell = (children, width, opts = {}) => new TableCell({
|
||||
borders: noBorders,
|
||||
width: { size: width, type: WidthType.DXA },
|
||||
children: Array.isArray(children) ? children : [children],
|
||||
...(opts.verticalAlign ? { verticalAlign: opts.verticalAlign } : {}),
|
||||
});
|
||||
|
||||
// ═══════════════════════════════════════════════
|
||||
// BLOCK BUILDERS — בוני הבלוקים
|
||||
// ═══════════════════════════════════════════════
|
||||
|
||||
// בלוק א — כותרת מוסדית (טבלה 2 טורים)
|
||||
function buildInstitutionalHeader(data) {
|
||||
const leftCol = CONTENT_WIDTH * 0.5;
|
||||
const rightCol = CONTENT_WIDTH * 0.5;
|
||||
|
||||
// צד ימין — מוסד
|
||||
const rightCellContent = [
|
||||
rtlPara(rtlRun("מדינת ישראל", { bold: true }), { alignment: AlignmentType.START, spacing: { after: 0 } }),
|
||||
rtlPara(rtlRun("ועדת ערר לתכנון ובניה"), { alignment: AlignmentType.START, spacing: { after: 0 } }),
|
||||
rtlPara(rtlRun("מחוז ירושלים"), { alignment: AlignmentType.START, spacing: { after: 80 } }),
|
||||
];
|
||||
|
||||
// צד שמאל — מספרי תיק
|
||||
const leftLines = [];
|
||||
if (data.case_numbers) {
|
||||
data.case_numbers.forEach(cn => {
|
||||
leftLines.push(rtlPara([
|
||||
rtlRun("מס' תיק: "),
|
||||
rtlRun(cn, { bold: true }),
|
||||
], { alignment: AlignmentType.START, spacing: { after: 0 } }));
|
||||
});
|
||||
}
|
||||
if (data.plan_number) {
|
||||
leftLines.push(rtlPara([
|
||||
rtlRun("מס' תכנית: "),
|
||||
rtlRun(data.plan_number, { bold: true }),
|
||||
], { alignment: AlignmentType.START, spacing: { after: 0 } }));
|
||||
}
|
||||
if (data.request_number) {
|
||||
leftLines.push(rtlPara([
|
||||
rtlRun("מס' בקשה: "),
|
||||
rtlRun(data.request_number, { bold: true }),
|
||||
], { alignment: AlignmentType.START, spacing: { after: 0 } }));
|
||||
}
|
||||
|
||||
return new Table({
|
||||
visuallyRightToLeft: true,
|
||||
width: { size: CONTENT_WIDTH, type: WidthType.DXA },
|
||||
columnWidths: [rightCol, leftCol],
|
||||
rows: [
|
||||
new TableRow({
|
||||
children: [
|
||||
rtlCell(rightCellContent, rightCol),
|
||||
rtlCell(leftLines.length ? leftLines : [rtlPara(rtlRun(""))], leftCol),
|
||||
]
|
||||
})
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
// בלוק ב — הרכב הוועדה
|
||||
function buildPanel(data) {
|
||||
const lines = [];
|
||||
lines.push(spacer(120));
|
||||
lines.push(rtlPara([
|
||||
rtlRun("בפני:", { bold: true }),
|
||||
], { spacing: { after: 40 } }));
|
||||
lines.push(rtlPara([
|
||||
rtlRun("יו\"ר הוועדה: ", { bold: true }),
|
||||
rtlRun(data.panel?.chair || "עו\"ד דפנה תמיר"),
|
||||
], { spacing: { after: 40 } }));
|
||||
|
||||
if (data.panel?.members) {
|
||||
lines.push(rtlPara([
|
||||
rtlRun("חברי הוועדה: ", { bold: true }),
|
||||
rtlRun(data.panel.members[0] || ""),
|
||||
], { spacing: { after: 40 } }));
|
||||
for (let i = 1; i < data.panel.members.length; i++) {
|
||||
lines.push(rtlPara(rtlRun(data.panel.members[i]), { spacing: { after: 40 } }));
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
// בלוק ג — צדדים
|
||||
function buildParties(data) {
|
||||
const lines = [];
|
||||
lines.push(spacer(120));
|
||||
|
||||
// עוררים
|
||||
if (data.appellants) {
|
||||
const label = data.appellants.length > 1 ? "העוררים:" : "העורר:";
|
||||
lines.push(rtlPara(rtlRun(label, { bold: true }), { spacing: { after: 40 } }));
|
||||
data.appellants.forEach(a => {
|
||||
lines.push(rtlPara(rtlRun(a.name), { spacing: { after: 20 } }));
|
||||
if (a.representative) {
|
||||
lines.push(rtlPara(rtlRun(`ע"י ב"כ ${a.representative}`), { spacing: { after: 20 } }));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// נגד
|
||||
lines.push(spacer(80));
|
||||
lines.push(rtlPara(rtlRun("נגד", { bold: true }), {
|
||||
alignment: AlignmentType.CENTER,
|
||||
spacing: { before: 80, after: 80 }
|
||||
}));
|
||||
|
||||
// משיבים
|
||||
if (data.respondents) {
|
||||
lines.push(rtlPara(rtlRun("המשיבים:", { bold: true }), { spacing: { after: 40 } }));
|
||||
data.respondents.forEach((r, i) => {
|
||||
lines.push(rtlPara(rtlRun(`${i + 1}. ${r.name}`), { spacing: { after: 20 } }));
|
||||
if (r.representative) {
|
||||
lines.push(rtlPara(rtlRun(`ע"י ב"כ ${r.representative}`), { spacing: { after: 20 } }));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
// בלוק ה — פתיחה
|
||||
function buildOpening(data) {
|
||||
const paras = [];
|
||||
if (data.opening_paragraphs) {
|
||||
data.opening_paragraphs.forEach((text, i) => {
|
||||
paras.push(numberedPara(i + 1, text));
|
||||
});
|
||||
} else {
|
||||
paras.push(numberedPara(1, `לפנינו ${data.appeal_description || "[תיאור הערר]"}.`));
|
||||
}
|
||||
return paras;
|
||||
}
|
||||
|
||||
// בלוק ו — רקע עובדתי
|
||||
function buildBackground(data) {
|
||||
const paras = [];
|
||||
let num = (data.opening_paragraphs?.length || 1) + 1;
|
||||
|
||||
if (data.use_petach_davar !== false) {
|
||||
paras.push(sectionTitle("פתח דבר"));
|
||||
}
|
||||
|
||||
// מקרקעין
|
||||
if (data.property_description) {
|
||||
paras.push(numberedPara(num++, data.property_description));
|
||||
} else {
|
||||
paras.push(numberedPara(num++, "[תיאור המקרקעין — מיקום, שטח, שכונה, ייעוד, מאפיינים ייחודיים]"));
|
||||
}
|
||||
|
||||
// היסטוריה תכנונית
|
||||
if (data.planning_history) {
|
||||
data.planning_history.forEach(text => {
|
||||
paras.push(numberedPara(num++, text));
|
||||
});
|
||||
} else {
|
||||
paras.push(numberedPara(num++, "[היסטוריה תכנונית — תכניות קודמות, החלטות קודמות, היתרים]"));
|
||||
}
|
||||
|
||||
// תמונה — מיקום
|
||||
paras.push(imageBox("תשריט מיקום המגרש מתוך מערכת GIS — לסמן את המגרש"));
|
||||
|
||||
// מהות הבקשה
|
||||
if (data.request_essence) {
|
||||
if (Array.isArray(data.request_essence)) {
|
||||
data.request_essence.forEach(text => {
|
||||
paras.push(numberedPara(num++, text));
|
||||
});
|
||||
} else {
|
||||
paras.push(numberedPara(num++, data.request_essence));
|
||||
}
|
||||
} else {
|
||||
paras.push(numberedPara(num++, "[מהות הבקשה — פירוט מלא של מה שהתבקש]"));
|
||||
}
|
||||
|
||||
// תמונה — תשריט
|
||||
paras.push(imageBox("תשריט הבקשה / נספח בינוי / תכנית מוצעת"));
|
||||
|
||||
// ציטוט מפרוטוקול
|
||||
if (data.committee_protocol_quote) {
|
||||
paras.push(numberedPara(num++, "להלן מתוך פרוטוקול הדיון בוועדה המקומית:"));
|
||||
paras.push(blockquote(data.committee_protocol_quote));
|
||||
} else {
|
||||
paras.push(numberedPara(num++, "[ציטוט מלא מפרוטוקול הוועדה המקומית]"));
|
||||
}
|
||||
|
||||
// החלטת הוועדה + תנאים
|
||||
if (data.committee_decision) {
|
||||
paras.push(numberedPara(num++, data.committee_decision));
|
||||
} else {
|
||||
paras.push(numberedPara(num++, "[החלטת הוועדה המקומית — מה הוחלט, אילו תנאים נקבעו]"));
|
||||
}
|
||||
|
||||
// תמונה אופציונלית — סביבה
|
||||
if (data.include_aerial_photo !== false) {
|
||||
paras.push(imageBox("צילום אוויר / מבט על הסביבה עם סימון המגרש"));
|
||||
}
|
||||
|
||||
// סביבת המקרקעין
|
||||
if (data.surroundings) {
|
||||
paras.push(numberedPara(num++, data.surroundings));
|
||||
}
|
||||
|
||||
// הגשת הערר
|
||||
if (data.appeal_filing) {
|
||||
paras.push(numberedPara(num++, data.appeal_filing));
|
||||
} else {
|
||||
paras.push(numberedPara(num++, "[הגשת הערר — תאריך, מי הגיש, הצטרפויות]"));
|
||||
}
|
||||
|
||||
return { paras, nextNum: num };
|
||||
}
|
||||
|
||||
// בלוק ז — טענות הצדדים
|
||||
function buildClaims(data, startNum) {
|
||||
const paras = [];
|
||||
let num = startNum;
|
||||
|
||||
paras.push(sectionTitle("תמצית טענות הצדדים"));
|
||||
|
||||
// טענות העוררים
|
||||
if (data.appellant_claims_sections) {
|
||||
// מספר עוררים עם כותרות נפרדות
|
||||
data.appellant_claims_sections.forEach(section => {
|
||||
paras.push(subTitle(section.title));
|
||||
section.claims.forEach(text => {
|
||||
paras.push(numberedPara(num++, text));
|
||||
});
|
||||
});
|
||||
} else {
|
||||
paras.push(subTitle("טענות העוררים"));
|
||||
if (data.appellant_claims) {
|
||||
data.appellant_claims.forEach(text => {
|
||||
paras.push(numberedPara(num++, text));
|
||||
});
|
||||
} else {
|
||||
paras.push(numberedPara(num++, "[טענות העוררים]"));
|
||||
}
|
||||
}
|
||||
|
||||
// עמדת הוועדה המקומית
|
||||
paras.push(subTitle("עמדת הוועדה המקומית"));
|
||||
if (data.committee_position) {
|
||||
data.committee_position.forEach(text => {
|
||||
paras.push(numberedPara(num++, text));
|
||||
});
|
||||
} else {
|
||||
paras.push(numberedPara(num++, "[עמדת הוועדה המקומית]"));
|
||||
}
|
||||
|
||||
// עמדת מבקשי ההיתר / מגישי התכנית
|
||||
const applicantTitle = data.type === "plan"
|
||||
? "עמדת מגישי התכנית"
|
||||
: "עמדת מבקשי ההיתר";
|
||||
paras.push(subTitle(applicantTitle));
|
||||
if (data.applicant_position) {
|
||||
data.applicant_position.forEach(text => {
|
||||
paras.push(numberedPara(num++, text));
|
||||
});
|
||||
} else {
|
||||
paras.push(numberedPara(num++, `[${applicantTitle}]`));
|
||||
}
|
||||
|
||||
return { paras, nextNum: num };
|
||||
}
|
||||
|
||||
// בלוק ח — ההליכים בפני ועדת הערר
|
||||
function buildProceedings(data, startNum) {
|
||||
const paras = [];
|
||||
let num = startNum;
|
||||
|
||||
paras.push(sectionTitle("ההליכים בפני ועדת הערר"));
|
||||
|
||||
if (data.proceedings) {
|
||||
data.proceedings.forEach(item => {
|
||||
if (item.type === "image") {
|
||||
paras.push(imageBox(item.description));
|
||||
} else if (item.type === "quote") {
|
||||
paras.push(numberedPara(num++, item.intro || ""));
|
||||
paras.push(blockquote(item.text));
|
||||
} else {
|
||||
paras.push(numberedPara(num++, item.text));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
paras.push(numberedPara(num++, "[דיון — תאריך, נוכחים, עיקרי הדברים]"));
|
||||
paras.push(numberedPara(num++, "[סיור (אם היה) — תאריך, תיאור]"));
|
||||
paras.push(imageBox("צילומים מהסיור"));
|
||||
paras.push(numberedPara(num++, "[החלטות ביניים]"));
|
||||
paras.push(numberedPara(num++, "[השלמות טיעון — כרונולוגי]"));
|
||||
paras.push(numberedPara(num++, "[חוו\"ד מקצועיות שהתקבלו]"));
|
||||
paras.push(imageBox("הדמיות / חתכי בינוי מהשלמות טיעון (אם יש)"));
|
||||
}
|
||||
|
||||
return { paras, nextNum: num };
|
||||
}
|
||||
|
||||
// בלוק ט — תכניות חלות (אופציונלי)
|
||||
function buildPlans(data, startNum) {
|
||||
if (data.skip_plans_section) return { paras: [], nextNum: startNum };
|
||||
|
||||
const paras = [];
|
||||
let num = startNum;
|
||||
|
||||
paras.push(sectionTitle("התכניות החלות על המקרקעין"));
|
||||
|
||||
if (data.applicable_plans) {
|
||||
data.applicable_plans.forEach(item => {
|
||||
if (item.type === "quote") {
|
||||
paras.push(numberedPara(num++, item.intro || ""));
|
||||
paras.push(blockquote(item.text));
|
||||
} else {
|
||||
paras.push(numberedPara(num++, item.text));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
paras.push(numberedPara(num++, "[פירוט התכניות הרלוונטיות עם ציטוט מהוראותיהן]"));
|
||||
}
|
||||
|
||||
return { paras, nextNum: num };
|
||||
}
|
||||
|
||||
// בלוק יב — חתימות
|
||||
function buildSignatures(data) {
|
||||
const chairName = data.panel?.chair || "עו\"ד דפנה תמיר";
|
||||
const secretaryName = data.secretary || "";
|
||||
|
||||
const halfWidth = Math.floor(CONTENT_WIDTH / 2);
|
||||
|
||||
return [
|
||||
spacer(400),
|
||||
rtlPara(rtlRun("ניתנה פה אחד, היום ______________, ______________."), {
|
||||
spacing: { after: 400 }
|
||||
}),
|
||||
new Table({
|
||||
visuallyRightToLeft: true,
|
||||
width: { size: CONTENT_WIDTH, type: WidthType.DXA },
|
||||
columnWidths: [halfWidth, halfWidth],
|
||||
rows: [
|
||||
new TableRow({
|
||||
children: [
|
||||
rtlCell([
|
||||
rtlPara(rtlRun("________________________"), { alignment: AlignmentType.CENTER, spacing: { after: 40 } }),
|
||||
rtlPara(rtlRun(chairName, { bold: true }), { alignment: AlignmentType.CENTER, spacing: { after: 20 } }),
|
||||
rtlPara(rtlRun("יו\"ר ועדת הערר"), { alignment: AlignmentType.CENTER, spacing: { after: 20 } }),
|
||||
], halfWidth),
|
||||
rtlCell([
|
||||
rtlPara(rtlRun("________________________"), { alignment: AlignmentType.CENTER, spacing: { after: 40 } }),
|
||||
rtlPara(rtlRun(secretaryName || ""), { alignment: AlignmentType.CENTER, spacing: { after: 20 } }),
|
||||
rtlPara(rtlRun("מזכירת ועדת הערר"), { alignment: AlignmentType.CENTER, spacing: { after: 20 } }),
|
||||
], halfWidth),
|
||||
]
|
||||
})
|
||||
]
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════
|
||||
// MAIN — הרכבת המסמך
|
||||
// ═══════════════════════════════════════════════
|
||||
|
||||
function buildDocument(data) {
|
||||
const content = [];
|
||||
|
||||
// בלוק א — כותרת מוסדית
|
||||
content.push(buildInstitutionalHeader(data));
|
||||
content.push(spacer(160));
|
||||
|
||||
// בלוק ב — הרכב
|
||||
content.push(...buildPanel(data));
|
||||
content.push(spacer(80));
|
||||
|
||||
// בלוק ג — צדדים
|
||||
content.push(...buildParties(data));
|
||||
content.push(spacer(160));
|
||||
|
||||
// בלוק ד — כותרת "החלטה"
|
||||
content.push(mainTitle("החלטה"));
|
||||
|
||||
// בלוק ה — פתיחה
|
||||
content.push(...buildOpening(data));
|
||||
|
||||
// בלוק ו — רקע
|
||||
const bg = buildBackground(data);
|
||||
content.push(...bg.paras);
|
||||
|
||||
// בלוק ז — טענות
|
||||
const claims = buildClaims(data, bg.nextNum);
|
||||
content.push(...claims.paras);
|
||||
|
||||
// בלוק ח — הליכים
|
||||
const proc = buildProceedings(data, claims.nextNum);
|
||||
content.push(...proc.paras);
|
||||
|
||||
// בלוק ט — תכניות (אופציונלי)
|
||||
const plans = buildPlans(data, proc.nextNum);
|
||||
content.push(...plans.paras);
|
||||
|
||||
// בלוק י — דיון והכרעה (placeholder)
|
||||
content.push(sectionTitle("דיון והכרעה"));
|
||||
content.push(placeholder("כאן מתחיל פרק הדיון וההכרעה — ייכתב בשלב הבא"));
|
||||
|
||||
// בלוק יא — סיכום (placeholder)
|
||||
content.push(sectionTitle("סיכום"));
|
||||
content.push(placeholder("ייכתב לאחר השלמת פרק הדיון"));
|
||||
|
||||
// בלוק יב — חתימות
|
||||
content.push(...buildSignatures(data));
|
||||
|
||||
return new Document({
|
||||
styles: {
|
||||
default: {
|
||||
document: {
|
||||
run: { font: FONT, size: FONT_SIZE, rightToLeft: true },
|
||||
paragraph: { bidirectional: true, alignment: AlignmentType.BOTH }
|
||||
}
|
||||
},
|
||||
paragraphStyles: [
|
||||
{
|
||||
id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal",
|
||||
quickFormat: true,
|
||||
run: { size: HEADING1_SIZE, bold: true, font: FONT, rightToLeft: true },
|
||||
paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0,
|
||||
bidirectional: true, alignment: AlignmentType.CENTER }
|
||||
},
|
||||
{
|
||||
id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal",
|
||||
quickFormat: true,
|
||||
run: { size: HEADING2_SIZE, bold: true, font: FONT, rightToLeft: true },
|
||||
paragraph: { spacing: { before: 200, after: 200 }, outlineLevel: 1,
|
||||
bidirectional: true, alignment: AlignmentType.CENTER }
|
||||
},
|
||||
]
|
||||
},
|
||||
sections: [{
|
||||
properties: {
|
||||
page: {
|
||||
size: { width: PAGE_WIDTH, height: PAGE_HEIGHT },
|
||||
margin: { top: MARGIN_DXA, right: MARGIN_DXA, bottom: MARGIN_DXA, left: MARGIN_DXA }
|
||||
},
|
||||
bidi: true,
|
||||
},
|
||||
footers: {
|
||||
default: new Footer({
|
||||
children: [new Paragraph({
|
||||
bidirectional: true,
|
||||
alignment: AlignmentType.CENTER,
|
||||
children: [
|
||||
rtlRun("עמוד ", { size: 18 }),
|
||||
new TextRun({ children: [PageNumber.CURRENT], font: FONT, size: 18 }),
|
||||
rtlRun(" מתוך ", { size: 18 }),
|
||||
new TextRun({ children: [PageNumber.TOTAL_PAGES], font: FONT, size: 18 }),
|
||||
]
|
||||
})]
|
||||
})
|
||||
},
|
||||
children: content
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════
|
||||
// CLI
|
||||
// ═══════════════════════════════════════════════
|
||||
|
||||
async function main() {
|
||||
const inputFile = process.argv[2];
|
||||
|
||||
if (!inputFile) {
|
||||
console.error('שימוש: node create-decision-structure.js <input.json> [output.docx]');
|
||||
console.error('');
|
||||
console.error('קובץ ה-JSON צריך לכלול:');
|
||||
console.error(' case_numbers, panel, appellants, respondents,');
|
||||
console.error(' opening_paragraphs, property_description, planning_history,');
|
||||
console.error(' request_essence, committee_protocol_quote, committee_decision,');
|
||||
console.error(' appellant_claims, committee_position, applicant_position,');
|
||||
console.error(' proceedings, applicable_plans');
|
||||
console.error('');
|
||||
console.error('ראה: .claude/skills/legal-decision/references/decision-template.json');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const data = JSON.parse(fs.readFileSync(inputFile, 'utf-8'));
|
||||
const outputFile = process.argv[3] || `החלטה-ערר-${(data.case_numbers?.[0] || 'draft').replace(/\//g, '-')}-מבנה.docx`;
|
||||
|
||||
const doc = buildDocument(data);
|
||||
const buffer = await Packer.toBuffer(doc);
|
||||
fs.writeFileSync(outputFile, buffer);
|
||||
|
||||
console.log(`✅ ${outputFile}`);
|
||||
console.log(` פונט: ${FONT} ${FONT_SIZE / 2}pt`);
|
||||
console.log(` שוליים: ${MARGIN_CM} ס"מ`);
|
||||
console.log(` RTL: bidi + bidirectional + rightToLeft ✓`);
|
||||
console.log(` Alignment: START/END ✓`);
|
||||
console.log(` גודל: ${(buffer.length / 1024).toFixed(1)} KB`);
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error('❌ שגיאה:', err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user