رفتن به محتوا

چاپ و خروجی نسل سوم

بستهٔ @darzsaz/report یک سند HTML آمادهٔ چاپ می‌سازد؛ PDF از پنجرهٔ چاپ مرورگر (وب) یا کروم بی‌سر (darzsaz pdf) می‌آید. این سند می‌گوید برگه‌ها چطور ساخته و صفحه‌بندی می‌شوند و چه تصمیم‌هایی پشتشان است.

paginate(blocks, { pageH, firstPageH?, gap? }) در src/paginate.ts تنها موتورِ صفحه‌بندی است (۱۱.۱): هر برگه از بلوک‌هایی با ارتفاعِ اندازه‌گرفته (میلی‌متر) پر می‌شود؛ بلوک نصف نمی‌شود و بلوک بلندتر از برگه، برگهٔ خودش را می‌گیرد. ردیفِ لیست برش (۸٫۵ و ۵٫۷ برای هر خطِ دیگرِ نام یا یادداشت، از پهنای متن — «جا شدن با متنِ همان زبان» پایین)، خلاصهٔ خرید (۳۱٫۶ + ۵٫۹ هر ردیفِ کارتِ بلندتر)، گروهِ برگهٔ خرید (عنوان و جدول، H در src/bom-page.ts)، ردیفِ نوار لبه (۷)، گامِ مونتاژ (۱۱۳)، ردیفِ برچسب، نوارِ سوراخ‌کاری، نقشهٔ کارگاهی و بخش‌های برگهٔ خلاصه (کادرِ «چاپ کنید» ۲۱٫۲، جدولِ ورق، دو کارت ۵۴٫۱، هشدارها با ردیفِ دوخطیِ ۱۲٫۲، فهرستِ بسته، رندرِ جلد ۱۳۳ — H در src/summary-page.ts، زیرِ printableH) همه بلوک‌اند. هر برگه جای آزادِ A4 ِ خودش را می‌گوید و spaceOn(box, mm) ِ src/paper.ts کوتاهیِ کاغذ را از آن کم می‌کند. تا ۱۱.۱ لیست برش، برچسب، نوار لبه و مونتاژ «n ردیف در برگه» ِ ثابت داشتند (R1). برابری روی A4 را test/golden.test.ts نشان داد: هیچ برگهٔ لیست برش، نوار لبه، مونتاژ، خلاصه یا خرید عوض نشد. خلاصهٔ خرید بلوکی با بلندیِ خودش است (بالا) و هر جا جا شود می‌نشیند — در پروژهٔ کوچک زیرِ ردیف‌های برگهٔ اول (جای ۲۰ ردیف)؛ ثابتِ «۱۸ ردیف» (۱۵۳ میلی‌متر) ِ نسخهٔ نخستِ همین موتور خلاصهٔ پروژهٔ زیرِ ۱۲ ردیف را به برگهٔ بعد می‌فرستاد.

جدولِ PAPER تنها جای اندازه، واژهٔ @page، نام و کاغذِ برچسبِ هر کاغذ است (R3: A4 در ده جا بود).

drillPages برای هر قطعهٔ سوراخ‌دار یا شیاردار (هم‌شکل‌ها یکی) طرحی به میلی‌متر واقعی می‌کشد (width="…mm" روی SVG). قطعه‌ای که در برگه جا نشود (۱۸۶ × ۲۳۶ روی A4، figureMaxH) کوچک نمی‌شود — دیگر ۱:۱ نبود. به‌جایش هر ردیف سوراخ یک نوار می‌شود (مثل شابلون) و نوار بلند به تکه‌های ۱۸۶ میلی‌متری با علامت شکست قرمز و مبدأ x=… y=… تقسیم می‌شود. زیر هر طرح نوار ۱۰۰ میلی‌متری هست (زیرِ ناحیهٔ کم‌پهناتر از ۱۰۰ میلی‌متر، کوتاه‌تر و گرد به ده): اگر چاپگر «جا کردن در صفحه» زده باشد، با خط‌کش معلوم می‌شود. مختصات همان قرارداد MachiningOp است؛ سوراخ لبه خط‌چین کشیده می‌شود.

drawingPages: برای هر دیوار نمای روبه‌رو (دیوار، بازشو، مانع، یونیت‌ها با برچسب، صفحهٔ کار، زنجیرهٔ عرض هر ردیف، ارتفاع صفحه و ردیف دیواری) و پلان (خط دیوار، عمق یونیت‌ها، طول). مقیاس از پهنای ۱۸۶ میلی‌متری برگه حساب و روی برگه نوشته می‌شود («مقیاس ۱:۱۶»)، مگر نقشه از جای آزادِ زیرِ سرصفحه (figureMaxH: ۲۳۶ روی A4) بلندتر شود — آن‌وقت مقیاس از بلندی می‌آید. تا پیش از کاغذ، مقیاس فقط از پهنا بود و نمای ۲۷۱ میلی‌متریِ آشپزخانهٔ small-180 و نمای l-shaped از A4 بیرون می‌زدند (۱۱۰٪ ِ برگه)؛ نقشه‌ای که جا می‌شد (نمای ۲۳۴٫۸ ِ آشپزخانهٔ نمونه) دست نخورد.

countertopPages از پیش بود (قطعه‌ها، درزها، برش‌ها) و در بستهٔ نصاب می‌آید.

هر برچسب یک QR ِ ۱۸ میلی‌متری دارد (qrSvg، از qrcode-generator، سطح تصحیح M) با حاشیهٔ خاموشِ چهار خانه که استاندارد می‌خواهد — تا ۱۱.۶ یک خانه در ۱۵ میلی‌متر بود؛ ۱۸ همان گامِ خانه را نگه می‌دارد. محتوا نسخه‌دار است و در وب و CLI یکی: partRef(projectId, physicalPartId)darzsaz:1/p/<id>/part/<partId> (src/part-ref.ts). نشانیِ استقرار دیگر روی کاغذ نمی‌آید: برچسبی که https://…/#/p/<id>/workshop?part= داشت با جابه‌جا شدنِ اپ (یا چاپ از localhost) مرده بود. خواننده (parsePartRef) نسخهٔ ۱ و نسخهٔ قدیمِ بی شماره — لینکِ کامل و darzsaz:#/p/… — را می‌خواند و نسخهٔ ناشناخته را null می‌دهد؛ اسکنرِ کارگاه آن را از زیرمسیرِ بی‌وابستگیِ @darzsaz/report/part-ref وارد می‌کند تا بقیهٔ بسته تنبل بماند. شناسهٔ هر تکهٔ فیزیکی از sourceIds قطعهٔ ادغام‌شده می‌آید. آزمون: test/part-ref.test.ts و test/bundles.test.ts QR را از خودِ SVG ِ برگه رستر و با jsqr رمزگشایی می‌کنند.

DXF با لایهٔ سوراخ (P6، ۱۱.۵)

Section titled “DXF با لایهٔ سوراخ (P6، ۱۱.۵)”

هر ورق یک پروندهٔ R12 (AC1009) با HEADER ($INSUNITS = 4 میلی‌متر، $EXTMIN/$EXTMAX) و TABLES (نوعِ خطِ CONTINUOUS و هشت لایه با رنگ): SHEET، PART، LABEL، OFFCUT، HOLE، GROOVE، NOTCH، GRIP (DXF_LAYERS؛ NOTCH the outline of a handle channel’s seat cut through a side, GRIP a routed grip — a J pull from the back, a finger groove from the face, on its own layer because the operator turns the part over for one and not the other). نامِ لایه انگلیسی است — ORAGH/SURAKH ِ لاتین‌نویس را اپراتورِ غیرفارسی نمی‌فهمید — و واحد دیگر ضمنی نیست. nestingDxf(nesting, cat, opsOf?): با opsOf (شناسهٔ قطعه → عملیات) سوراخ‌های رویه به لایهٔ HOLE (CIRCLE) و شیارها به GROOVE می‌روند — هر شیار کانتورِ بسته‌ای به عرضِ خودش (دو لبه و دو سر)، نه خطِ مرکزیِ بی عرض. A notch (the seat of a handle channel in a side) is a closed four-line outline on NOTCH; the drill sheet draws it hatched with its name («فاقِ پروفیلِ دستگیرهٔ مخفی»). آزمون با dxf-parser (test/dxf.test.ts): واحد، محدوده، لایه‌ها و شیارِ دولبه روی قطعهٔ صاف و چرخیده. قطعهٔ چرخیده روی ورق، x قطعه‌اش روی y ورق می‌رود. ⚠️ رو/پشت قطعه را نمی‌دانیم؛ اپراتور CNC خودش تعیین می‌کند. سوراخ لبه در نقشهٔ ورق معنی ندارد و نمی‌آید.

darzsaz export --xlsx سه برگه می‌نویسد: لیست برش، لیست خرید، ورق‌ها (apps/cli/src/workbook.ts). نویسنده (xlsx.ts) کمینه و خودمان است: زیپ (fflate) از چند XML با رشتهٔ درون‌خطی و عدد عددی، جهتِ برگه از زبانِ خط فرمان (fa-IR راست‌به‌چپ، en-US چپ‌به‌راست)، سرستون پررنگ. SheetJS نیامد: نسخهٔ npm آن (۰٫۱۸٫۵) رها شده و دو آسیب‌پذیری باز دارد و نسخهٔ تازه فقط از CDN خودشان می‌آید. فقط در CLI، تا بستهٔ وب سنگین نشود. نام، واحد و یادداشتِ «لیست خرید» — مثل bomCsv(i18n, report) — پیامِ هسته‌اند و به زبانِ خط فرمان بی نویسهٔ جداسازِ جهت رندر می‌شوند: خانهٔ جدول جمله نیست (i18n.md).

مبلغ به واحدِ پروژه (۹.۶)

Section titled “مبلغ به واحدِ پروژه (۹.۶)”

برگهٔ خرید و darzsaz bom صورت‌حساب را با costIn(report, settings.currency) (src/money.ts) به واحدِ پروژه نشان می‌دهند و تاریخِ برداشتِ مرجعِ دفتر (capturedAt) را کنارِ تاریخِ قیمت‌ها؛ دفتر و CostReport به واحدِ خودشان می‌مانند. تا پیش از این دفترِ تومانی در پروژهٔ ریالی عددِ تومان را با واژهٔ «ریال» چاپ می‌کرد (test/bom-page.test.ts، apps/cli/test/prices-reference.test.ts).

مرکز چاپ و بسته‌های مخاطب (P8)

Section titled “مرکز چاپ و بسته‌های مخاطب (P8)”

BUNDLES در src/bundles.ts: «همه»، «برشکار» (خلاصه، لیست برش، نقشهٔ ورق، نوار لبه، برچسب)، «نصاب» (خلاصه، نقشهٔ کارگاهی، مونتاژ، سوراخ‌کاری، برش‌های صفحه، برگهٔ صفحه)، «مشتری» (خلاصه با رندر و لیست خرید). bundleReport(input, id) سند را می‌سازد؛ fullReport همان «همه» است. ورودی Derived است (...derive(project, cat)): هشدارهای خلاصه (issues) و صورت‌حساب (bom) از همان می‌آیند و برگه قاعده‌ها و buildBom را دوباره اجرا نمی‌کند (۱۱.۲؛ جاسوس در test/derived-only.test.tswithBom ِ مرده رفت. جدولِ هشدارِ خلاصه هشت ردیف دارد و بقیه «… و N مورد دیگر» می‌شوند، نه بریدنِ بی‌صدا. برگهٔ خلاصه فهرست «این بسته چه دارد» را از همان کلیدها می‌سازد. در وب، Ctrl+P مرکز چاپ را باز می‌کند: انتخاب بسته، زبان برگه و کاغذ، پیش‌نما در قاب ایزوله (sandbox)، چاپ/PDF، دانلود HTML، و «فرستادن…». نام و راهنمای هر بسته پیام است (BUNDLES[id].label) — در مرکز چاپ به زبانِ رابط، در عنوانِ سند به زبانِ برگه.

shareFiles(files, title) در apps/web/src/lib/share.ts با navigator.share؛ دکمه فقط وقتی می‌آید که canShareFiles() بگوید پرونده پشتیبانی می‌شود. انصراف کاربر «cancelled» است، نه خطا.

شماره‌های فهرست به رقمِ زبانِ سند (ol:lang(fa) { list-style-type: persian }؛ سندِ انگلیسی decimal)، هر عدد با قالب‌گرِ زبانِ سند (doc.fmt)، ارقام هم‌عرض در ستون‌های عددی (tabular-nums@page ِ کاغذِ سند بدون حاشیهٔ مرورگر تا صفحه‌بندی دست خودمان بماند. جهتِ برگه منطقی است (text-align: start/end، inset-inline): همان CSS راست‌به‌چپ و چپ‌به‌راست درست می‌نشیند.

زبانِ سند فقط ReportInput.i18n است. docOf(i18n, paper) (src/doc.ts) یک بار برای هر سند locale را از خودِ i18n.locale می‌خواند — زبانِ ناشناخته خطاست — و lang، dir، قالب‌گرِ عدد و تاریخ و هر پیام از همان می‌آیند. فیلدِ locale ِ دومی در ورودی نیست تا نمونهٔ فارسی با locale: 'en-US' ساختنی نباشد (test/locale.test.ts با @ts-expect-error می‌سنجد). تا پیش از این renderDocument زبان می‌پذیرفت و bundleReport هرگز نمی‌داد (I9).

تاریخ ایزو است. ReportInput.date و AssemblyOptions.date روزِ YYYY-MM-DD اند (today() ِ هسته) و برگه به تقویم و رقمِ خودش قالبشان می‌زند: «۱۴۰۵/۶/۲۲» و «9/13/26». رشتهٔ دیگر خطاست (printDay)، نه متنی که دست‌نخورده چاپ شود — فراخوانِ کهنه تاریخِ شمسی را روی برگهٔ انگلیسی می‌نشاند.

پیامِ برگه. هر رشته پیامِ report.* است، با سه تابعِ Doc:

تابع برای فرار
d.t(M.x) پیامِ متنی همه‌اش
d.h(M.x) جمله‌ای با <b>/<br> ِ خودِ کاتالوگ فقط مقدارها (متنِ کاربر، تو در تو هم)
d.m(msg) پیامِ هسته (برچسبِ قطعه، قاعده، گام) همه‌اش

«همهٔ ابعاد اندازهٔ برش است» یک جمله است و تأکیدِ میانش جای خودش را در ترجمه دارد؛ بریدنش به سه پیام همان چسباندنِ تکه بود. test/messages.test.ts می‌سنجد هیچ پیامِ report.* در هیچ کاتالوگی جز <b>، </b> و <br> نشانه یا & ندارد. واژه‌ای که چند برگه با همان معنا می‌خوانند یک شناسه دارد (WORD در src/common.ts: سرستون‌ها، «(ادامه)»، جداکنندهٔ فهرست ، /, ، «٪»). نامِ نقش در راهنمای رنگِ نقشهٔ ورق همان واژه‌نامهٔ هسته است (shortPartLabel).

دادهٔ کاربر درونِ متنِ روان جدا می‌شود (iso()، همان FSI/PDI ِ text()): «نامِ پروژه · 9/13/26» بی آن در برگهٔ انگلیسی «9/13/26 · نام» خوانده می‌شد. نامی که تنها محتوای خانه است (<td>، <h1>) لازم ندارد. عنوانِ سند بی جداساز است: نامِ پیش‌فرضِ پرونده در «Save as PDF» است.

کاغذِ پیش‌فرض با زبانِ برگه (۱۰.۷): مرکز چاپ برای برگهٔ en-US Letter و برای fa-IR A4 می‌گذارد (PAPER_OF در apps/web/src/lib/locale.ts) — تا وقتی کاربر خودش کاغذی انتخاب نکرده، عوض کردنِ زبانِ برگه کاغذ را هم عوض می‌کند؛ پس از انتخاب، انتخابِ او می‌ماند (test/print-center.dom.test.tsx).

کاغذ: A4 و Letter (src/paper.ts). A3/A5 نیامدند — هیچ مخاطبی برگهٔ برش را روی آن‌ها نمی‌خواهد و هر کاغذ ظرفیتِ خودش را می‌خواهد. paperCss @page، قابِ هر برگه، سقفِ نقشهٔ ورق و شبکهٔ کاغذِ برچسب را می‌دهد (--paper-*، --cutmap-max-height، --label-*sheet.css از همان متغیرها می‌خواند. Letter ۱۷٫۶ میلی‌متر کوتاه‌تر است و هر جای اندازه‌گرفته روی A4 همان‌قدر کم می‌شود (spaceOn):

ظرفیت A4 Letter
ردیفِ لیست برش (اول/بعدی) ۲۰/۲۹ ۱۷/۲۶
برچسب در برگه (کاغذِ برچسب) ۲۴: ۳ × ۸ ِ ۷۰ × ۳۷ ۳۰: ۳ × ۱۰ ِ ۶۶٫۶۷۵ × ۲۵٫۴
ردیفِ نوار لبهٔ قطعه‌به‌قطعه ۳۰ ۲۷
گامِ مونتاژ ۲ ۲
بلندیِ شکل (سوراخ‌کاری، نقشه) ۲۳۶ mm ۲۱۸٫۴ mm
سقفِ نقشهٔ ورق ۸۸ mm ۷۰٫۴ mm
کفِ نقشهٔ ورق (.fill) ۵۰ mm ۵۰ mm
گامِ حروفِ برچسب (متن/درشت) ۱۱/۱۵px، خط ۱٫۶ ۱۰/۱۴px، خط ۱٫۲۵، حاشیه ۱٫۵

برگهٔ برچسب خودِ کاغذِ برچسب است (۱۱.۱): <section class="page label-sheet"> بی سرصفحه و پانویس، شبکه با اندازه، حاشیهٔ بالا و کنار و فاصلهٔ همان کاغذ، و مرزِ خانه فقط روی صفحهٔ نمایش، نه روی کاغذ. تا پیش از این ۲۴ کارتِ ۲۶ میلی‌متری با فاصلهٔ ۴ بود که با هیچ کاغذِ بازار نمی‌خواند (R3). کاغذِ برچسبِ دلخواه (کاتالوگِ کاربر) کارِ پنلِ مدیریت است؛ امروز هر کاغذ رایج‌ترین کاغذِ برچسبِ خودش را دارد و کاربر با «مرکز چاپ ▸ کاغذ» به آن می‌رسد.

SVG ِ فنی (نقشهٔ ورق، سوراخ‌کاری، نقشهٔ کارگاهی، برشِ صفحه) direction="ltr" و هر <text> لنگرِ صریح دارد (۱۱.۳، R5)؛ قلم در هر دو زبان اول وزیرمتنِ جاسازی‌شده است و پشتیبانش از زبان (body:lang(en) لاتین)، شمارهٔ فهرست ol:lang(fa) فارسی. فونت یک بار در هر سند (۱۱.۷، test/sheet-markup.test.ts) — و از نسل ششم (۰.۱) فراخوان آن را می‌دهد (fontFaces ِ ReportInput/AssemblyOptions): خط فرمان base64 ِ @darzsaz/report/fonts، رابط پروندهٔ پیش‌انباشت‌شدهٔ fonts/Vazirmatn-print.woff2 را هنگامِ ساختِ سند جاسازی می‌کند (apps/web/src/lib/print-font.ts) تا base64 در جاوااسکریپتِ وب نباشد (fonts.md) — و یک بار در هر بستهٔ خروجی: «خروجی‌ها» ِ رابط دیگر assembly.html ِ جدا نمی‌دهد — برگه‌های مونتاژ درونِ darzsaz.html (بستهٔ «همه») هستند؛ آشپزخانهٔ نمونه ۱٬۳۲۸٬۶۸۵ ← ۱٬۰۳۳٬۰۸۶ بایت (−۲۹۵٬۵۹۹، ثبت‌شده کنارِ exportPack در apps/web/src/lib/actions.ts؛ apps/web/test/export-pack.test.ts یک @font-face در کلِ بسته را می‌سنجد). مرکز چاپ سندِ هر بسته × زبان × کاغذ × روز را برای همان Derived نگه می‌دارد (apps/web/src/lib/print-sheet.ts).

سنجش با چاپِ PDF در کروم (preferCSSPageSize) و شمردنِ صفحه‌های PDF در برابرِ <section class="page"> — هر سرریز یک صفحهٔ PDF ِ اضافه است — روی ۲۱ پیکرهٔ فارسی (آشپزخانهٔ نمونه، ده آشپزخانهٔ KITCHENS، سه الگو، پروژهٔ خالی، ال، قیمت‌دار، CNC، خطادار، جلددار)، بستهٔ «همه»:

کاغذ صفحهٔ PDF ِ اضافه برگهٔ سرریز به نوع
A4 پیش از ۳.۵ ۴۴ خلاصه ۱۱، لیست برش ۹، خرید ۱۸، نقشهٔ ورق ۴، نقشهٔ کارگاهی ۲
A4 پس از ۳.۵ ۴۲ همان، بی نقشهٔ کارگاهی
Letter ۴۱ خلاصه ۱۸، لیست برش ۱، خرید ۱۸، نقشهٔ ورق ۴؛ مونتاژ، برچسب و سوراخ‌کاری صفر

سرریزهای این جدول تا ۱۱.۱ بسته شدند — خلاصه، برگهٔ خرید و لیست برش با paginate، و نقشهٔ ورق در قابِ کاغذ («جا شدن با متنِ همان زبان» پایین).

پذیرشِ ۱۱.۱ در e2e (apps/web/e2e/print-heights.spec.ts، ۶۶ آزمون): بستهٔ «همه» ِ آشپزخانهٔ نمونه، ده KITCHENS و lShapedProject (بی یونیت) در A4 و Letter × دو زبان در کرومِ چاپگر و با وزیرمتنِ جاسازی‌شده (vazirmatnFontFaces، همان که مرکز چاپ و خط فرمان می‌دهند؛ آزمون می‌سنجد که همان قلم رندر شده — بی آن کروم قلمِ سامانه را می‌گیرد و جدولِ text-metrics.ts بی‌معناست: در نسل ششم، فاز ۰، سرِ دوخطیِ سوراخ‌کاریِ u-300-240-300 ِ انگلیسی سه خط و برگهٔ ۶۰ از ۷۷ ۰٫۹ میلی‌متر از A4 بلندتر شد)، با نامِ یونیت‌ها به زبانِ برگه؛ بسته‌های «نصاب» و «برشکار» ِ آشپزخانهٔ نمونه و ال؛ پهنای نمای مرورگر همان پهنای کاغذ، بلندیِ هر section.page (با scrollHeight) زیرِ کاغذ، پایینِ محتوا بالای خطِ پانویس، شمارِ صفحهٔ PDF برابرِ شمارِ برگه، هر برچسب درونِ خانه‌اش (scrollHeight) و پروژهٔ بی قطعه بی برگهٔ برچسب؛ و آشپزخانه با نامِ یونیتِ بلند روی Letter (نامِ قطعه دو خط و «…»، هیچ کارتی بریده نه). سنجیده (۱۴۰۵/۰۶/۲۳)، پیش ← پس از صفحه‌بندیِ خلاصه و گامِ حروفِ برچسب:

کاغذ · زبان نصاب: برگه / صفحهٔ PDF بلندترین برگهٔ نصاب برشکار: برگه / صفحهٔ PDF برچسبِ بریده (از ۵۸)
A4 · fa-IR ۶۶/۶۷ ← ۶۷/۶۷ ۲۹۷٫۷ ← ۲۹۱٫۵ از ۲۹۷ ۱۵/۱۵ ← ۱۶/۱۶ ۰ ← ۰ (خانهٔ ۳۷ mm)
A4 · en-US ۶۶/۶۷ ← ۶۷/۶۷ ۳۰۹٫۱ ← ۲۹۱٫۵ از ۲۹۷ ۱۵/۱۷ ← ۱۶/۱۷ ۰ ← ۰
Letter · en-US ۷۳/۷۴ ← ۷۴/۷۴ ۳۰۹٫۱ ← ۲۷۵٫۱ از ۲۷۹٫۴ ۱۵/۱۷ ← ۱۶/۱۷ ۳۰ ← ۰ (خانهٔ ۲۵٫۴)
Letter · fa-IR ۷۳/۷۴ ← ۷۴/۷۴ ۲۹۷٫۷ ← ۲۷۵٫۱ از ۲۷۹٫۴ ۱۵/۱۶ ← ۱۶/۱۶ ۲۱ ← ۰

خلاصه تا ۱۱.۱ تنها برگهٔ متن‌دارِ بی صفحه‌بندی بود (۲۵۴٫۶ فارسی و ۲۶۶ انگلیسی زیرِ سرصفحه، در برابرِ ۲۵۰ ِ printableH)؛ حالا بلوک‌هایش با paginate می‌ریزند و فهرستِ «این بسته چه دارد» ِ آشپزخانهٔ نمونه به برگهٔ «خلاصه (ادامه)» می‌رود — تنها برگه‌های طلاییِ عوض‌شده (برگهٔ ۱ و برگهٔ تازهٔ ۲ ِ «همه»). برچسبِ Letter گامِ حروفِ خودش را از PAPER.Letter.labels.type می‌گیرد: چهار گام روی ۱۲۳۷ کارت (آشپزخانهٔ نمونه و ده KITCHENS × دو زبان) صفر بریده دادند و درشت‌ترین ماند؛ A4 همان ۱۱/۱۵ است. پروژهٔ بی قطعه دیگر برگهٔ برچسبِ خالی نمی‌سازد.

لیست برشِ انگلیسی (۱۱.۱): ردیفش دوخطی بود (۱۴٫۲ mm در برابرِ ۸٫۵ ِ مدل) — نه از نامِ قطعه، از ستونِ جنس: جدولِ خودکار پهنا را به نسبتِ محتوای هر ستون پخش می‌کند، یادداشتِ کنارِ نامِ قطعه ستونِ قطعه را ۸۸٫۸ mm می‌خواست (مجموع ۲۰۵٫۹ از ۱۹۰) و «ام‌دی‌اف ملامینه سفید» در ستونِ ۳۰ میلی‌متری در همهٔ ردیف‌ها می‌پیچید؛ در جاروی ده KITCHENS روی A4 از ۴۶۷ ردیفِ دوخطیِ انگلیسی ۴۰۱ فقط جنس بود، و فارسی هم در سه پیکره ۵۶ ردیف داشت. حالا نامِ جنس nowrap است، یادداشت خطِ خودش را زیرِ نام دارد و مدل ردیفِ یادداشت‌دار را ۱۴٫۲ می‌شمارد، و برگهٔ ادامه ۲۹ ردیف است (ادامهٔ پرِ ۳۰ ردیفی ۳۰۰٫۷ mm بود). برگهٔ خرید دیگر یک section نیست: هر گروه بلوک است و گروهِ بلندتر از برگه با «(ادامه)» بریده می‌شود. آشپزخانهٔ نمونه، پیش ← پس:

برگه A4 Letter
لیست برشِ انگلیسی، برگهٔ اول ۳۶۱٫۵ ← ۲۴۹٫۱ mm ۳۲۴٫۶ ← ۲۳۲٫۰ mm
لیست برش (هر دو زبان) ۲ برگه ← ۲ ۳ برگه ← ۲
برگهٔ خرید (همه) ۴۶۵٫۸ ← ۲۳۷٫۹ + ۲۷۱٫۰ ۴۶۵٫۸ ← ۲۳۷٫۹ + ۲۷۱٫۰

جاروی آشپزخانهٔ نمونه و ده KITCHENS، بستهٔ «همه»، برگه‌های بلندتر از کاغذ پیش ← پس: لیست برش A4 ِ فارسی ۸ ← ۰، Letter ِ فارسی ۱ ← ۰، A4 ِ انگلیسی ۲۳ ← ۸، Letter ِ انگلیسی ۲۴ ← ۸؛ برگهٔ خرید ۴۴ ← ۰. آن ۸ برگهٔ انگلیسی (نامِ قطعهٔ ادغام‌شدهٔ بلند) در بندِ پایین بسته شدند.

جا شدن با متنِ همان زبان (۱۱.۱، پایان)

Section titled “جا شدن با متنِ همان زبان (۱۱.۱، پایان)”

پهنای متن پیش از چاپ (src/text-width.ts): جدولِ پهنای پیش‌رویِ فونتِ جاسازی‌شده (src/text-metrics.ts، ساختهٔ node scripts/report-metrics.mjs در کروم) برای وزنِ ۴۰۰ و ۷۰۰: هر نویسه، چهار شکلِ حرفِ فارسی (تنها، آغازین، میانی، پایانی با ZWJ)، لام‌الف (یک نشانه، ۰٫۰۱۷ em پهن‌تر از دو شکل) و ۲۳۲ جفتِ حرف که فونت پهن‌ترشان می‌کشد («پی» ۱۳۶‰). گرد به بالا، کرنینگِ منفی نه، شکست فقط در فاصلهٔ ASCII. سنجیده روی ۲٬۱۳۴ متنِ پیکره (نامِ قطعه، یادداشت، جنس، ترتیبِ برش؛ دو زبان) در سه قلم: از ۴۱٬۰۱۹ واژه صفر کمتر از کروم، و نامِ بلند تا ۰٫۴٪ بیشتر. اثرِ انگشتِ فونت در جدول است؛ test/text-width.test.ts پس از pnpm format:fonts می‌گوید جدول را از نو بساز.

  • لیست برش (src/cutlist-rows.ts): ستونِ «قطعه» در جدولِ خودکار دست‌کم «پهنای جدول منهای بیشینهٔ هشت ستونِ دیگر» است، چون آن ستون‌ها کمینه‌شان همان بیشینه است — عدد، جنسِ nowrap، طرحِ نوار، و سرِ ستونِ nowrap (.fit th؛ «Edge banding» دوخطی می‌شد و سرِ جدول ۵٫۴ بلندتر از مدل). از ۲٬۴۵۲ ردیفِ ۱۱ آشپزخانه × ۴: صفر ردیف کم‌خط‌تر از کروم، ۲ ردیف یک خط بیشتر.
  • نقشهٔ ورق (src/cutmap-fit.ts): برگه قابِ .fill به بلندیِ کاغذ است و نقشه با فلکس جای باقی را می‌گیرد، تا کفِ ۵۰ میلی‌متر (CUTMAP_MIN_HplanSheet می‌گوید جدولِ قطعه‌ها و ترتیبِ برش کنارِ نقشه‌ای به بلندیِ کف + ۱۰ جا می‌شوند یا نه، و آنچه نشود به «نقشهٔ برش — ورق n از m (ادامه)» می‌رود (فقط ترتیبِ برش: همان «ترتیب برش — ورق n»). کوچک‌ترین نقشهٔ پیکره ۶۱٫۸ میلی‌متر، ۳۹ نقشه زیرِ سقف.
  • سوراخ‌کاری (src/drill-page.ts): سرِ طرح با شمارِ خطِ همان متن (۵٫۴ هر خط)، خطِ «بخش i از n» ۵٫۹ (مدلِ پیشین ۱۶ و ۴)، و جای برگه اندازه‌گرفته (کاغذ − ۲۴ − سرصفحه − ۳ − ۱)، نه printableH − 16.
  • پانویس درونِ حاشیهٔ پایین است (bottom: 5.5mm، خطِ ۱٫۳): در چاپ برگه بلندیِ کمینه ندارد و پانویسِ پیشین خطش را ۳٫۳ میلی‌متر روی ردیفِ آخرِ هر برگه می‌کشید.

جاروی ۱۱ آشپزخانه × A4/Letter × فارسی/انگلیسی، بستهٔ «همه»، پیش ← پس: برگهٔ بلندتر از کاغذ ۷۰ ← ۰ (لیست برشِ انگلیسی ۸+۸، نقشهٔ ورق فارسی ۴+۴ و انگلیسی ۲۳+۲۱، سوراخ‌کاریِ انگلیسی ۲)؛ برگه با محتوای زیرِ پانویس ۳٬۰۰۲ ← ۰؛ همهٔ برگه‌ها ۵٬۹۲۴ ← ۵٬۷۶۷ (سوراخ‌کاری ۲٬۶۷۰ ← ۲٬۴۹۶ با جای اندازه‌گرفته؛ نقشه و ادامه‌اش در انگلیسی +۶ و +۸؛ لیست برشِ انگلیسی +۱ و +۲). بلندترین برگه: لیست برش ۲۸۹٫۳ از ۲۹۷ و ۲۷۲٫۳ از ۲۷۹٫۴، سوراخ‌کاری ۲۹۵٫۶ و ۲۷۷٫۹. طلایی: دو برگهٔ لیست برش (کلاسِ fit، همان ردیف‌ها)، پنج برگهٔ نقشهٔ ورق (قابِ .fill، همان جدول و ترتیبِ برش) و سوراخ‌کاری ۴۰ ← ۳۹ برگه (همان ۱۴۶ طرح) عوض شدند.

نامِ بلند روی برچسب دو خط و «…» است (.label .name، -webkit-line-clamp): کارت برای نامِ دوخطی اندازه شده و نامِ سه‌خطی تهِ کارت را زیرِ overflow: hidden ِ خانه بی‌صدا می‌برید. نامِ کامل در title ِ همان خانه و نامِ دسترس‌پذیرِ QR می‌ماند؛ آشپزخانه با نامِ یونیتِ بلند روی Letter ۱۵ از ۵۸ نام کوتاه شد، صفر کارت بریده.

برگهٔ فارسیِ A4 همان ماند. از ۱۴۸ خروجیِ فارسی (۱۰۶ سند و ۴۲ CSV، ۲۱ پیکره)، ۱۴۴ پیش و پس از پیام شدن پس از یکسان‌سازی (CSS کنار، FSI/PDI برداشته، فاصله‌ها یکی) برابرند، با دو تغییرِ عمدی که پیش از مقایسه روی خروجیِ قدیم نشست: خانهٔ جمعِ صورت‌حساب text-align:leftend (همان سمت در راست‌به‌چپ) و گروهِ countertop ِ خامِ CSV که حالا «صفحهٔ کابینت» است. چهار سندِ دیگر بسته‌های «همه» و «نصاب» ِ small-180 و l-shaped اند — همان نقشه‌های کارگاهی‌ای که از A4 بیرون می‌زدند. عکسِ کرومِ ۳۲۲ برگه (۶ سند، نمایش و چاپ): ۹۷ برگه حداکثر ۲۸۹ پیکسل فرق دارند، همه لبه‌گیریِ زیرپیکسلی در نوارهای ≤ ۱۳ پیکسلیِ یک خط کنارِ نویسهٔ جداساز — نه جابه‌جاییِ متن. test/golden.test.ts درهم‌سازِ هر <section class="page"> ِ «همه» (برگهٔ برچسب نه) و مونتاژِ آشپزخانهٔ نمونه را با golden/kitchen-fa-a4.json می‌سنجد — ساخته از خروجیِ پیش از پیام شدن و از نو نوشته با هر تغییرِ عمدی (GOLDEN=write، ۱۱.۱).

مرکز چاپ. «زبان برگه» (پیش‌فرض زبانِ رابط) و «کاغذ» (پیش‌فرض کاغذِ زبانِ برگه — A4 برای فارسی، Letter برای انگلیسی؛ بالا). برگهٔ به زبانِ دیگر نمونهٔ i18n ِ خودش را دارد: sheetI18n(locale) (apps/web/src/lib/print-sheet.ts) کاتالوگ را با همان نقشهٔ تنبلِ رابط (loadCatalog ِ lib/locale.ts) بار می‌کند و createI18n می‌سازد — زبانِ رابط هرگز عوض نمی‌شود. darzsaz export/pdf/assemble برگه را به زبانِ cliI18n ِ خط فرمان و روزِ today() می‌نویسند — زبان از --lang، سپس DARZSAZ_LANG (پیش‌فرض فارسی)، و همیشه A4: خط فرمان گزینهٔ کاغذ ندارد (apps/cli/test/report-docs.test.ts پیش‌فرضِ فارسی و A4 را می‌سنجد).

CSS ِ برگه بی کامنت به سند می‌رود (DOC_CSS): کامنتِ فارسیِ sheet.css برای خوانندهٔ کد است؛ هر سند ۶۰۰ بایت سبک‌تر و برگهٔ انگلیسی از سر تا ته بی حرفِ فارسی.

پژوهش Typst-WASM (P11) 🔶 — رد شد

Section titled “پژوهش Typst-WASM (P11) 🔶 — رد شد”

معیار: بارگذاری تنبل ≤ ۴ مگابایت و فارسی بی‌نقص. اندازه‌گیری (npm view، ۱۴۰۵/۰۶/۱۸): @myriaddreamin/typst-ts-web-compiler ۲۸٫۴ مگابایت، رندرکننده ۱٫۱ مگابایت، بستهٔ اصلی ۱٫۴ مگابایت — کامپایلر به تنهایی هفت برابر سقف. چاپ مرورگر می‌ماند؛ PDF واقعی از CLI (darzsaz pdf با کروم بی‌سر).