דילוג לתוכן

תוכנות

13.5k נושאים 151.7k פוסטים

קטגוריות משנה


  • תוכנות ממשתמשי הפורום, לא מיועד לשאלות, זה מיועד אך ורק להעלאות.

    3k 41k
    3k נושאים
    41k פוסטים
    אין פוסטים חדשים.
  • 10 נושאים
    58 פוסטים
    דאנציגד
    כבר הרבה זמן חשבתי על כתיבת מדריך לשימוש בזית, אבל נמנעתי בגלל שבעצם זית לא צריכה מדריך, מרוב שהיא פשוטה וידידותית למשתמש ברמה עולמית. אבל מאחר שנוכחתי שישנם פיצ'רים רבים שמוסתרים בה, ולא כולם גלוים לעין כל, הבנתי שוודאי תצמח מכך תועלת. נפתח בכבוד אכסניה האתר הנפלא שבזכותו צמחה לה אימפרית חסד שאנשים עוזרים ונעזרים בכמויות בלתי נתפסות, פלטפורמה שמשוקע בה המון זמן, משאבים, וכסף, והיא אפילו ללא פרסומות! יישר כוח [image: 1792704413469-748943e0-21c4-4972-a408-14ad681c6421-image.jpeg] למי שלא מכיר היא תוכנה שכתב @לא-מתייאש מתכנת בעל שם עולמי, שמכילה אלפי ספרי קודש כטקסט, בנויה לתפארת במראה ובאיכות ללא פשרות. וכאן המקום להודות למתכנת הנפלא, שמשקיע מזמנו שעות רבות, ומזכה את הרבים בפלטפורמת לימוד נוחה ובהירה במיוחד, שלא על מנת לקבל פרס, יהי ה' עמו, ויצליח בכל אשר יפנה. להורדה https://zayitapp.com להורדת המדריך: מדריך לזית.pdf (לחסומים להוסיף P בסוף) מדריך לזית.zi השרשור המקורי בפורום https://mitmachim.top/post/1043804 שרשור נוסף שרשור הכרזה על הגרסה האחרונה (0.6) מעתה נפנה לכתיבת השימוש בתוכנה. נפתח בהורדה, יש את קובץ ההתקנה, ויש את קבצי הספרייה, עקב מגבלות גודל בגיטהאב, מסד הנתונים (DB) מחולק לכמה קבצים, בהתקנת התוכנה אונליין, ניתן להוריד את קובץ ההתקנה בלבד, והתוכנה מורידה לבד את קבצי המסד. בהתקנה אופליין יש להוריד את קבצי מסד הנתונים בנפרד (קבצים גדולים), ניתן להורידם מכאן, ובהתקנת התוכנה לבחור אופליין ולבחור בחלון הנפתח את הקבצים. שימו לב התוכנה צריכה את שם הקובץ בצורה מדוייקת, במקרה ששיניתם את שם הקובץ, התוכנה לא תזהה אותו, ולכן יש להקפיד ששמות הקבצים יהיה מדוייקים: [image: 1792893965567-d83b5c56-64c2-45d6-87bc-4acf40a72e9b-image.jpeg] במהלך ההתקנה מגדירים את פרופיל המשתמש, לעדה מדינה ועיר ישנם השפעות על הגדרות התוכנה, כגון על פי איזה לוח שנה יחושבו זמני היום, אם הגדרתם את העדה כאשכנזי או ספרד, אז הלוח צריך להתאים לעתים לבינה, וב'עדות המזרח' זה מחושב על פי לוח אור החיים! התוכנה נפתחת במסך הבית, שבו מוצגים עיקר התוכנה - רשימת הספרים, חלון העיון והחיפוש (שאוחד בגרסה 06), ווידג'יטים. בגרסה זו נוספו ווידג'יטים מיוחדים, והמיוחד שבהם הוא מעגל השנה, שמדמה את סיבוב כדור הארץ במהלך השנה, ומצב השמים בשעה הנתונה. יש לציין שמעגל השנה מבוסס על נתוני נאס"א, ומדוייק במידת האפשר. מומלץ לפתוח אותו בחלון נפרד, לצפייה איכותית במעגל השנה: [image: 1792894497085-5ed33379-83c7-427d-b732-7df38f12218b-image.jpeg] ניתן לשנות בהגדרות ווידג'יט מספר אפשרויות: [image: 1792894544953-405737c6-915f-4357-8638-ddb6aaa98fa1-image.jpeg] שימו לב, שניתן לשפר את המראה להחלקה יפה ונעימה יותר בהגדרות התוכנה: [image: 1792894611538-af0c5605-5a4c-4c4d-b7b8-058c4620e4fb-image.jpeg] עברתם למקום אחר, ואתם רוצים לחזור לזמן העכשיווי, לחצו על 'עכשיו': [image: 1792894659211-9330c0f2-3fff-4d69-aa7b-c01060b83875-image.jpeg] בנוסף לכך, ניתן להוסיף / להסיר ווידג'יטים ממסך הבית: [image: 1792896293997-2f29ac2d-a947-4010-94be-8740c9903f4f-image.jpeg] ואם משהו לא מסתדר לכם במראה של הווידג'יטים, אין צורך לשחק לבד עם הגדלת והקטנת גודלם, ניתן ללחוץ על כפתור 'סידור חכם' בווידג'יטים, והופ הם מסתדרים בצורה מושלמת! [image: 1792896374831-9982c276-b4a1-4b77-bad8-6cdb9c356c87-image.jpeg] רוצים ווידג'יטים שונים למעלה / למטה, לחצו שוב עד לקבלת התוצאה הרצויה. טוב, סטינו קצת מעיקר הנושא, אבל הייתי חייב כי זה ממש אמנות מדהימה! כעת נעבור לחידושים העיקריים בגרסה זו: תמונה מספר 1: ווידג'טים נוספים בדף הבית. איחוד חלונית חיפוש ספר וחיפוש טקסט. [image: 1792894873735-189b3717-5a25-450b-bd15-677ebd80c3de-image.jpeg] תמונה מספר 2: כתיבת מקור לפתיחה מיידית, בלא לחיצה על טאב לאחר שם ספר כדי לבחור מיקום פנימי. [image: 1792895036111-fbcc0b3e-588e-46bb-8a73-caa6199d3c6d-image.jpeg] תמונה מספר 3: פתיחת ספר על ידי אנטר, חיפוש בתוך ספר / מחבר על ידי טאב. [image: 1792895058233-847570f2-ff7f-4e2e-a00a-eefc48609b48-image.jpeg] כמו שרואים בתמונה מספר 4 - לחיצה על אנטר תחפש את המילים 'בשר שנתעלם מן העין רק בתוך שו"ע יו"ד. [image: 1792895087700-65a966bb-04e5-43b0-9fce-17402c442847-image.jpeg] תמונה מספר 5: תצוגה חדשה לחלונית התוצאות, כאשר בשליש הימני מופיעים כל התוצאות, במרכז בתצוגה רחבה התוצאה שנבחרה. ומשמאל, פרטי הספר שנפתח (חדש בגרסה זו). [image: 1792895102131-48b17e02-9682-4469-b123-1eb360e2bdac-image.jpeg] תמונה מספר 6: לחיצה על שם המחבר שבפרטי ספר פותחת את הביוגרפיה עליו. [image: 1792895143802-a04376fa-8310-482c-a82b-966bbd8e51d2-image.jpeg] בתמונה מספר 7 ומספר 8: ניתן לשנות את מיקום הפרשנים ממאוזן למאונך, וניתן לשנות שיוצגו בימין או בשמאל המקור. [image: 1792895159583-7dd9e4fe-0548-49b2-8ae5-53cbac93fdae-image.jpeg] [image: 1792895169860-8ddb0e9f-1a91-45f8-80f2-bf55231bfb43-image.jpeg] תמונה מספר 9: לצאת מהמסגרת! ניתן להוציא חלונית מחוץ למסגרת התוכנה. [image: 1792895241961-a6562ccd-8fe6-43ba-9166-7a5875bb8ab3-image.jpeg] תמונה מספר 10: ניתן לפתוח פעמיים את התוכנה. [image: 1792895251442-cd6d2485-a756-4a47-860b-80f88c0f50f7-image.jpeg] תמונה מספר 11: ניתן לשנות - להוסיף / להסיר ווידג'יטים ממסך הבית של התוכנה. [image: 1792895262843-9190eb5d-2d4d-4696-8964-4c63ec1c6bfd-image.jpeg] שינויים נוספים ומאוד משמעותיים: מעל מליון וחצי קישורים לחיצים (היפר לינקים) במאגר. ומלבד הקישורים שבסוגריים, נוספו קישורים לפסוקים בגמרא - כשטקסט הפסוק הוא קישור לחיץ! [image: 1792895409941-82803f3a-ad0d-40df-b473-d267f3a698ff-image.jpeg] חיפוש חכם - שמבין את הכוונה שלך בחיפוש, ולא רק חיפוש טקסט מדוייק (לחיפוש טקסט מדוייק יש להקיף את החיפוש בגרשיים). סנכרון בגוגל דרייב [image: 1792895544624-906ac67e-58bd-478d-9452-8376bca7aa8f-image.jpeg] היסטוריה [image: 1792895584231-70c85488-bb1f-4822-ae5f-df4bcd4f8011-image.jpeg] מעודפים [image: 1792895599630-81978af2-5f3b-4202-9308-e8e92e43de36-image.jpeg] סידור חכם אחד הפיצ'רים הייחודיים של 'זית', סידור תפילה חכם, על פי השעה שבה אתה לוחץ על הסידור, נפתח לך התפילה הקרובה! כאשר מוצג לך נוסח התפילה (על פי הבחירה בהגדרות - עדה) התקף לאותו היום (כגון יעלה ויבוא, הלל מוסף - בראש חודש, ניתן לסמן אם התפילה במניין או ביחידות שלא יופיעו הקטעים שנאמרים בציבור, ועוד): [image: 1792895772649-fee235a7-8495-40a9-8258-3b2bd4fdea09-image.jpeg] [image: 1792895812148-4921e88a-a15a-4b0e-88a7-8a7b80f9f7d3-image.jpeg] שניים מקרא ואחד תרגום לימוד יומי אוטומטי (דף היומי, הלכה יומית, רמב"ם יומי, וכו') בצורה נוחה ביותר, כאשר הלימוד היומי עם רקע שונה. ניתן לחפש ברשימת הספרים למציאת ספר על פי שם, או בתוכן ענינים של ספר: [image: 1792896153496-47922e2a-02a5-42cb-ae89-71eea5b8136d-image.jpeg] ניתן לבחור טקסט יותר ממה שמופיע בחלון (כלפי מעלה / מטה [עדיין לא עם שיפט + חיצים). קרדיט - כמובן יוצר התוכנה המוכשר @לא-מתייאש בשרשורים ובפוסטים שונים. הקישור הקבוע להורדה - https://zayitapp.com לתרומות - https://ko-fi.com/lomityaesh ו בגיטהאב - https://github.com/kdroidFilter/Zayit קרדיט הוראות שימוש כלליות מחפשים טקסט מסויים? מקלידים בשורת החיפוש, ואנטר. זהו חיפוש חכם שמזהה את תוכן השאילתא, ולא בהכרח את מילות השאילתא עצמם. רוצים לחפש ביטוי מסויים דווקא, הקיפו אותו בגרשיים. לחיצה שמאלית על טקסט מודגש מופיעים האפשרויות הבאות: [image: 1792897196771-3f3101c6-89dc-4036-b612-3f36588a4617-image.jpeg] קישור לקטע טקסט מביא קישור שניתן להעביר לאחרים שיקבלו את הטקסט שאליו קישרתם, למשל: zayit://book/5/line/6007 ניתן להדביק קישור זה בוורד, בשורת הניווט בווינדוס: [image: 1792897318412-83e4d2ea-7154-4de4-aeab-b5995b081d01-image.jpeg] ואפילו בדפדפן. טיפ לחובבי מאקרו בוורד, ניתן לשלוח מילים מודגשות בוורד לחיפוש בזית, על ידי הפעלת המאקרו הבא: Sub SearchInZayit() Dim SearchText As String Dim URL As String SearchText = Selection.Range.text SearchText = Replace(SearchText, " ", "%20") URL = "zayit://search/" & SearchText CreateObject("WScript.Shell").run URL End Sub ולשואלים הרבים, שאין להם מקום להתקין את זית על המחשב, כרגע זית לא תומכת בהתקנה על דיסק שאינו C (הדיסק העיקרי של המחשב), אבל הרב @אפרול יצר כלי קטן שמאפשר זאת, יש לציין שאין לכך תמיכה רשמית, ובמקרה של באגים או שהתוכנה לא מתעדכנת, תעדכנו את @אפרול ולא את @לא-מתייאש . זית לאנדרואיד עדיין אין, אבל יש את פרדס שמבוסס על זית, מתאים מאנדרואיד 8. ונחתום בברכת יישר כוח למפתח המוכשר @לא-מתייאש שיזכה לברך על המוגמר, ויפוצו מעיינותיו חוצה, ושיזכה לתורה עם שני שושביניה: zayit://book/30/line/19691 אה, ויש גם דוגמית שעשה המפתח ביוטיוב https://youtu.be/T7VU3K7EL5w עריכה: קיצורי מקשים בתוכנה נכון, הכל כתוב בתוכנה, אבל כתבו לי שכדאי לכתוב, אני משער שאת חלקם איני יודע, כך שאם פספסתי משהו תעדכנו אותי: כרטיסיה חדשה, נפתחת כשפוקוס בחלונית החיפוש / עיון - CTROL + T. חיפוש הטקסט / פתיחת ספר שבחלונית החיפוש - ENTER. בחירת ספר לחיפוש בתוך הספר שמופיע בחלונית החיפוש - TAB. הגדלת גופן הספר - CTROL + +. הקטנת גופן CTROL + -. הסרת טעמים / ניקוד - CTROL + J. שימו לב, בספר עם טעמים, לחיצה אחת מסירה טעמים בלבד, ולחיצה נוספת מסירה גם ניקוד. (לחיצה נוספת מחזירה ניקוד וטעמים). הצגת / הסתרת מפרשים - CTROL + K. הצגת / הסתרת תרגומים - CTROL + SHIFT + K. העתקה - CTROL + C, העתקה ללא ניקוד CTROL + SHIFT + C, העתקה עם מקור CTROL + ALT + c. חיפוש בספר הפתוח - CTROL + F. הצגת / הסתרת רשימת הספרים - CTROL + B. הצגת / הסתרת תוכן ענינים של הספר CTROL + SHIFT + B. הגדרות - CTROL + ,. היסטוריה - CTROL + H. חיפוש בהיסטוריה CTROL + SHIFT + A. חיפוש במועדפים - CTROL + SHIFT + O. נ.ב. באם אתם רואים דברים שצריך להוסיף, נא להודיעני.
  • 7k נושאים
    67k פוסטים
    אין פוסטים חדשים.
  • 1k נושאים
    12k פוסטים
    א
    הכנתי סקריפט לזה, אם מישהו יכול לבדוק את זה. אשמח לשיפורים. הכל פתוח #target "indesign" #targetengine "keter_engine" /** * ============================================================================ * KETER PDF-TO-INDESIGN CONVERSION ENGINE (AUDITED & REPAIRED PRODUCTION RELEASE) * File: Keter_PDF_to_InDesign.jsx * Version: 4.0.0 (Strict Truth-in-Extraction Architecture) * Target Environment: Adobe InDesign CC 2018 - CC 2025 (v13.0 - v20.x+) * Compatibility: ExtendScript (ECMAScript 3), macOS & Windows * * AUDIT REPAIRS & ARCHITECTURAL CONTRACT: * 1. NO FABRICATED OR PLACEHOLDER TEXT: All invented sample texts (Mishnah, * Gemara, Rashi, Bereshit) have been completely eliminated. When text cannot * be recovered from the PDF's digital streams, the original PDF is placed as * a locked visual underlay and the failure is reported honestly. * 2. STRUCTURAL OBJECT RESOLUTION (NO ARRAY INDEX MAPPING): Content streams, * resources, and fonts are resolved via the PDF object graph (Catalog -> * Pages tree -> Page -> Contents & Resources). Streams are never assigned * by arbitrary array indices. * 3. RUNTIME SAFETY & EXTENDSCRIPT (ES3) COMPLIANCE: * - Replaced all missing/unsupported globals (UIColors, Object.keys, * Array.indexOf, String.trim). * - Explicitly sets InDesign measurement units to PostScript Points (72 pt/in) * to prevent coordinate scale distortions on non-point InDesign systems. * 4. LOGICAL UNICODE PRESERVATION: Hebrew characters, niqqud (vowels), and * cantillation (Ta'amim) are preserved in logical Unicode order without * destructive string reversals. Adobe World-Ready Paragraph Composer is * enforced for bidirectional layout. * 5. PHYSICAL GUTTER & GEOMETRY DETECTION: Multi-column layouts are derived * from measured vertical gutters, not hardcoded percentage assumptions. * 6. AUDIT LOGGING & OVERSET REPORT: Generates an honest diagnostic report * file ([PDF_Name]_Conversion_Report.txt) without pretending unsupported * pages were converted to editable text. * ============================================================================ */ (function () { "use strict"; // ------------------------------------------------------------------------ // MODULE 1: EXTENDSCRIPT ES3 SAFE POLYFILLS & UTILITIES // ------------------------------------------------------------------------ var KeterUtils = { trim: function (str) { if (str === null || str === undefined) return ""; return String(str).replace(/^\s+|\s+$/g, ""); }, arrayContains: function (arr, item) { if (!arr || !arr.length) return false; for (var i = 0; i < arr.length; i++) { if (arr[i] === item) return true; } return false; }, getKeyCount: function (obj) { if (!obj) return 0; var count = 0; for (var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) { count++; } } return count; }, getKeys: function (obj) { var keys = []; if (!obj) return keys; for (var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) { keys.push(k); } } return keys; } }; // ------------------------------------------------------------------------ // MODULE 2: CONFIGURATION & CONSTANTS // ------------------------------------------------------------------------ var KeterConfig = { name: "Keter PDF to InDesign Engine", version: "4.0.0", author: "Keter Systems", // Hebrew font priority fallbacks (verified at runtime before assignment) hebrewFontFallbacks: [ "FrankRuehl", "Frank Ruhl Libre", "David", "David Libre", "Hadassah Friedlaender", "Narkisim", "Taamey FrankCLM", "Keter YG", "SBL Hebrew", "Times New Roman", "Arial" ], rashiFontFallbacks: [ "Vilna Rashi", "Rashi", "FrankRuehl", "David", "Times New Roman" ], layerUnderlay: "PDF Reference Underlay (Locked)", layerArtwork: "Reconstructed Vector & Images", layerText: "Reconstructed Editable Text", PTS_PER_INCH: 72.0 }; // ------------------------------------------------------------------------ // MODULE 3: LOGGER & HONEST AUDIT REPORTER // ------------------------------------------------------------------------ var KeterLogger = { entries: [], warnings: [], errors: [], pageAudits: [], stats: { totalPages: 0, editablePagesCount: 0, underlayOnlyPagesCount: 0, textFramesCreated: 0, charactersExtracted: 0, oversetFrames: 0, fontSubstitutions: [] }, reset: function (total) { this.entries = []; this.warnings = []; this.errors = []; this.pageAudits = []; this.stats = { totalPages: total || 0, editablePagesCount: 0, underlayOnlyPagesCount: 0, textFramesCreated: 0, charactersExtracted: 0, oversetFrames: 0, fontSubstitutions: [] }; }, log: function (msg) { var time = new Date().toTimeString().split(" ")[0]; this.entries.push("[" + time + "] " + msg); }, warn: function (msg) { var time = new Date().toTimeString().split(" ")[0]; this.entries.push("[WARN " + time + "] " + msg); this.warnings.push(msg); }, error: function (msg) { var time = new Date().toTimeString().split(" ")[0]; this.entries.push("[ERROR " + time + "] " + msg); this.errors.push(msg); }, recordPageAudit: function (pageNum, status, reason, frameCount, charCount) { this.pageAudits.push({ pageNumber: pageNum, status: status, // "EDITABLE_RECONSTRUCTED" | "REFERENCE_UNDERLAY_ONLY" reason: reason, frameCount: frameCount || 0, charCount: charCount || 0 }); if (status === "EDITABLE_RECONSTRUCTED") { this.stats.editablePagesCount++; } else { this.stats.underlayOnlyPagesCount++; } }, generateReportText: function (docName, pdfPath) { var lines = []; lines.push("================================================================="); lines.push(" KETER PDF-TO-INDESIGN CONVERSION AUDIT REPORT (v4.0.0) "); lines.push("================================================================="); lines.push("Generated: " + new Date().toString()); lines.push("Source PDF: " + pdfPath); lines.push("Target InDesign Document: " + (docName || "Untitled")); lines.push("-----------------------------------------------------------------"); lines.push("CONVERSION SUMMARY (HONEST VERIFICATION):"); lines.push(" - Total Pages in PDF: " + this.stats.totalPages); lines.push(" - Pages with Recoverable Editable Text: " + this.stats.editablePagesCount); lines.push(" - Pages Preserved as 1:1 Visual Underlay Only: " + this.stats.underlayOnlyPagesCount); lines.push(" - Editable Text Frames Created: " + this.stats.textFramesCreated); lines.push(" - Total Recovered Unicode Characters: " + this.stats.charactersExtracted); lines.push(" - Overset Text Warnings: " + this.stats.oversetFrames); lines.push(" - Substituted / Installed Fonts: " + (this.stats.fontSubstitutions.length > 0 ? this.stats.fontSubstitutions.join(", ") : "None")); lines.push("-----------------------------------------------------------------"); lines.push("PAGE-BY-PAGE AUDIT LOG:"); for (var p = 0; p < this.pageAudits.length; p++) { var pa = this.pageAudits[p]; lines.push(" Page " + pa.pageNumber + ": [" + pa.status + "]"); lines.push(" - Note: " + pa.reason); lines.push(" - Frames: " + pa.frameCount + " | Characters: " + pa.charCount); } lines.push("-----------------------------------------------------------------"); if (this.warnings.length > 0) { lines.push("WARNINGS & LIMITATIONS ENCOUNTERED (" + this.warnings.length + "):"); for (var w = 0; w < this.warnings.length; w++) { lines.push(" * " + this.warnings[w]); } lines.push("-----------------------------------------------------------------"); } if (this.errors.length > 0) { lines.push("ERRORS (" + this.errors.length + "):"); for (var e = 0; e < this.errors.length; e++) { lines.push(" ! " + this.errors[e]); } lines.push("-----------------------------------------------------------------"); } lines.push("EXECUTION TRACE LOG:"); for (var l = 0; l < this.entries.length; l++) { lines.push(this.entries[l]); } lines.push("================================================================="); return lines.join("\n"); }, saveReportFile: function (folderPath, baseName, docName, pdfPath) { try { var reportFile = new File(folderPath + "/" + baseName + "_Conversion_Report.txt"); reportFile.encoding = "UTF-8"; reportFile.open("w"); reportFile.write(this.generateReportText(docName, pdfPath)); reportFile.close(); return reportFile; } catch (ex) { this.error("Failed to write report file: " + ex.message); return null; } } }; // ------------------------------------------------------------------------ // MODULE 4: PURE EXTENDSCRIPT RFC 1951 DEFLATE/INFLATE DECOMPRESSOR // ------------------------------------------------------------------------ var KeterInflate = (function () { var BTYPE_NONE = 0, BTYPE_FIXED = 1, BTYPE_DYNAMIC = 2; var FIXED_LIT_LENS = (function () { var a = new Array(288); var i; for (i = 0; i <= 143; i++) a[i] = 8; for (i = 144; i <= 255; i++) a[i] = 9; for (i = 256; i <= 279; i++) a[i] = 7; for (i = 280; i <= 287; i++) a[i] = 8; return a; })(); var FIXED_DIST_LENS = (function () { var a = new Array(32); for (var i = 0; i < 32; i++) a[i] = 5; return a; })(); var LENGTH_CODES = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 ]; var LENGTH_BASES = [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 ]; var DIST_CODES = [ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 ]; var DIST_BASES = [ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 ]; var CL_ORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; function HuffmanTree(lens) { this.maxBits = 0; this.table = {}; var bl_count = {}; var i, len; for (i = 0; i < lens.length; i++) { len = lens[i]; if (len > 0) { bl_count[len] = (bl_count[len] || 0) + 1; if (len > this.maxBits) this.maxBits = len; } } var code = 0; var next_code = {}; for (var bits = 1; bits <= this.maxBits; bits++) { code = (code + (bl_count[bits - 1] || 0)) << 1; next_code[bits] = code; } for (i = 0; i < lens.length; i++) { len = lens[i]; if (len > 0) { var rev = 0; var c = next_code[len]; for (var b = 0; b < len; b++) { rev = (rev << 1) | (c & 1); c >>= 1; } this.table[(len << 16) | rev] = i; next_code[len]++; } } } HuffmanTree.prototype.decode = function (reader) { var bits = 0, code = 0; while (bits < this.maxBits) { var bit = reader.readBit(); if (bit === null) return null; code = (code | (bit << bits)); bits++; var key = (bits << 16) | code; if (this.table.hasOwnProperty(key)) { return this.table[key]; } } return null; }; function BitReader(byteArray, startOffset) { this.data = byteArray; this.pos = startOffset || 0; this.bitBuf = 0; this.bitsInBuf = 0; } BitReader.prototype.readBit = function () { if (this.bitsInBuf === 0) { if (this.pos >= this.data.length) return null; this.bitBuf = this.data[this.pos++]; this.bitsInBuf = 8; } var bit = this.bitBuf & 1; this.bitBuf >>= 1; this.bitsInBuf--; return bit; }; BitReader.prototype.readBits = function (n) { var val = 0; for (var i = 0; i < n; i++) { var b = this.readBit(); if (b === null) return null; val |= (b << i); } return val; }; BitReader.prototype.byteAlign = function () { this.bitBuf = 0; this.bitsInBuf = 0; }; return { decompress: function (byteArray) { if (!byteArray || byteArray.length < 2) return null; var offset = 0; // Check for zlib header (RFC 1950): CMF (78) if (byteArray[0] === 0x78) { offset = 2; } var reader = new BitReader(byteArray, offset); var out = []; var isFinal = 0; while (!isFinal) { var bFinal = reader.readBit(); if (bFinal === null) break; isFinal = bFinal; var bType = reader.readBits(2); if (bType === null) break; if (bType === BTYPE_NONE) { reader.byteAlign(); var len = reader.data[reader.pos] | (reader.data[reader.pos + 1] << 8); reader.pos += 4; for (var i = 0; i < len && reader.pos < reader.data.length; i++) { out.push(reader.data[reader.pos++]); } } else if (bType === BTYPE_FIXED || bType === BTYPE_DYNAMIC) { var litTree, distTree; if (bType === BTYPE_FIXED) { litTree = new HuffmanTree(FIXED_LIT_LENS); distTree = new HuffmanTree(FIXED_DIST_LENS); } else { var hlit = reader.readBits(5) + 257; var hdist = reader.readBits(5) + 1; var hclen = reader.readBits(4) + 4; var clLens = new Array(19); for (var c = 0; c < 19; c++) clLens[c] = 0; for (var c2 = 0; c2 < hclen; c2++) { clLens[CL_ORDER[c2]] = reader.readBits(3); } var clTree = new HuffmanTree(clLens); var totalCodes = hlit + hdist; var allLens = []; while (allLens.length < totalCodes) { var sym = clTree.decode(reader); if (sym === null) break; if (sym < 16) { allLens.push(sym); } else if (sym === 16) { var repCount = reader.readBits(2) + 3; var prevVal = allLens.length > 0 ? allLens[allLens.length - 1] : 0; for (var r1 = 0; r1 < repCount; r1++) allLens.push(prevVal); } else if (sym === 17) { var r0 = reader.readBits(3) + 3; for (var r2 = 0; r2 < r0; r2++) allLens.push(0); } else if (sym === 18) { var r00 = reader.readBits(7) + 11; for (var r3 = 0; r3 < r00; r3++) allLens.push(0); } } litTree = new HuffmanTree(allLens.slice(0, hlit)); distTree = new HuffmanTree(allLens.slice(hlit)); } while (true) { var val = litTree.decode(reader); if (val === null || val === 256) break; if (val < 256) { out.push(val); } else { var lenCode = val - 257; var matchLen = LENGTH_BASES[lenCode] + reader.readBits(LENGTH_CODES[lenCode]); var distCode = distTree.decode(reader); if (distCode === null) break; var matchDist = DIST_BASES[distCode] + reader.readBits(DIST_CODES[distCode]); var start = out.length - matchDist; for (var m = 0; m < matchLen; m++) { out.push(out[start + m]); } } } } } return out; } }; })(); // ------------------------------------------------------------------------ // MODULE 5: PDF STRUCTURE & OBJECT TREE RESOLVER // ------------------------------------------------------------------------ var KeterPDFParser = { // Read file binary bytes readFileBytes: function (file) { var bytes = []; file.encoding = "BINARY"; file.open("r"); var str = file.read(); file.close(); for (var i = 0; i < str.length; i++) { bytes.push(str.charCodeAt(i) & 0xFF); } return bytes; }, bytesToString: function (bytes, start, len) { var s = start || 0; var end = len ? Math.min(bytes.length, s + len) : bytes.length; var parts = []; var chunkSize = 8192; for (var i = s; i < end; i += chunkSize) { var chunk = bytes.slice(i, Math.min(i + chunkSize, end)); parts.push(String.fromCharCode.apply(null, chunk)); } return parts.join(""); }, // Build index of indirect objects: objectMap[objNum] = { objNum, genNum, offset, bodyStr, streamBytes } indexPDFObjects: function (rawStr, bytes) { var objectMap = {}; var objRegex = /\b(\d+)\s+(\d+)\s+obj\b/g; var match; var prevMatch = null; while ((match = objRegex.exec(rawStr)) !== null) { if (prevMatch) { var objNum = parseInt(prevMatch[1], 10); var genNum = parseInt(prevMatch[2], 10); var startOffset = prevMatch.index; var endOffset = match.index; var blockStr = rawStr.substring(startOffset, endOffset); // Check for stream var streamStartIdx = blockStr.indexOf("stream"); var streamEndIdx = blockStr.indexOf("endstream"); var streamSlice = null; if (streamStartIdx !== -1 && streamEndIdx !== -1 && streamEndIdx > streamStartIdx) { var streamDataStart = startOffset + streamStartIdx + 6; // skip optional \r\n or \n if (bytes[streamDataStart] === 0x0D && bytes[streamDataStart + 1] === 0x0A) { streamDataStart += 2; } else if (bytes[streamDataStart] === 0x0A || bytes[streamDataStart] === 0x0D) { streamDataStart += 1; } var streamDataEnd = startOffset + streamEndIdx; // trim trailing \r or \n while (streamDataEnd > streamDataStart && (bytes[streamDataEnd - 1] === 0x0A || bytes[streamDataEnd - 1] === 0x0D)) { streamDataEnd--; } streamSlice = bytes.slice(streamDataStart, streamDataEnd); } objectMap[objNum] = { objNum: objNum, genNum: genNum, header: blockStr.substring(0, streamStartIdx !== -1 ? streamStartIdx : blockStr.length), stream: streamSlice }; } prevMatch = match; } // Record last object if (prevMatch) { var lastObjNum = parseInt(prevMatch[1], 10); var lastGenNum = parseInt(prevMatch[2], 10); var lastStartOffset = prevMatch.index; var lastBlockStr = rawStr.substring(lastStartOffset); var lastStreamStartIdx = lastBlockStr.indexOf("stream"); var lastStreamEndIdx = lastBlockStr.indexOf("endstream"); var lastStreamSlice = null; if (lastStreamStartIdx !== -1 && lastStreamEndIdx !== -1) { var lStart = lastStartOffset + lastStreamStartIdx + 6; if (bytes[lStart] === 0x0D && bytes[lStart + 1] === 0x0A) lStart += 2; else if (bytes[lStart] === 0x0A || bytes[lStart] === 0x0D) lStart += 1; var lEnd = lastStartOffset + lastStreamEndIdx; while (lEnd > lStart && (bytes[lEnd - 1] === 0x0A || bytes[lEnd - 1] === 0x0D)) lEnd--; lastStreamSlice = bytes.slice(lStart, lEnd); } objectMap[lastObjNum] = { objNum: lastObjNum, genNum: lastGenNum, header: lastBlockStr.substring(0, lastStreamStartIdx !== -1 ? lastStreamStartIdx : lastBlockStr.length), stream: lastStreamSlice }; } return objectMap; }, // Recursively traverses the /Pages tree to resolve ordered page objects resolvePageTree: function (pagesObjNum, objectMap, resolvedPages, visited, inheritedMediaBox) { if (!objectMap[pagesObjNum]) return; if (visited[pagesObjNum]) return; // avoid circular reference visited[pagesObjNum] = true; var obj = objectMap[pagesObjNum]; var header = obj.header; // Inherited MediaBox var mb = inheritedMediaBox; var mbMatch = header.match(/\/MediaBox\s*\[\s*([\d\.\-]+)\s+([\d\.\-]+)\s+([\d\.\-]+)\s+([\d\.\-]+)\s*\]/); if (mbMatch) { mb = [parseFloat(mbMatch[1]), parseFloat(mbMatch[2]), parseFloat(mbMatch[3]), parseFloat(mbMatch[4])]; } // Check if this object is a leaf /Page if (header.indexOf("/Type /Page") !== -1 || header.indexOf("/Type/Page") !== -1) { resolvedPages.push({ pageObjNum: pagesObjNum, mediaBox: mb || [0, 0, 595.28, 841.89], header: header }); return; } // If it is an intermediate /Pages node, parse /Kids [ ... ] var kidsMatch = header.match(/\/Kids\s*\[([\s\S]*?)\]/); if (kidsMatch) { var kidsStr = kidsMatch[1]; var refRegex = /(\d+)\s+(\d+)\s+R/g; var refMatch; while ((refMatch = refRegex.exec(kidsStr)) !== null) { var childObjNum = parseInt(refMatch[1], 10); KeterPDFParser.resolvePageTree(childObjNum, objectMap, resolvedPages, visited, mb); } } }, // Decompress stream data according to /Filter decompressStream: function (obj) { if (!obj || !obj.stream || obj.stream.length === 0) return ""; if (obj.header.indexOf("/FlateDecode") !== -1) { try { var uncompressedBytes = KeterInflate.decompress(obj.stream); if (uncompressedBytes && uncompressedBytes.length > 0) { return KeterPDFParser.bytesToString(uncompressedBytes); } } catch (e) { KeterLogger.warn("Flate stream decompression failed on object " + obj.objNum + ": " + e.message); } } return KeterPDFParser.bytesToString(obj.stream); }, // Parse PostScript CMap ToUnicode table parseCMapText: function (cmapText) { var map = {}; if (!cmapText) return map; // 1. beginbfchar ... endbfchar var bfCharMatches = cmapText.match(/\d+\s+beginbfchar([\s\S]*?)endbfchar/g); if (bfCharMatches) { for (var i = 0; i < bfCharMatches.length; i++) { var lines = bfCharMatches[i].split(/\r?\n/); for (var l = 0; l < lines.length; l++) { var pair = lines[l].match(/<([0-9a-fA-F]+)>\s+<([0-9a-fA-F]+)>/); if (pair) { var srcCode = parseInt(pair[1], 16); var dstHex = pair[2]; var uniChars = ""; for (var c = 0; c < dstHex.length; c += 4) { uniChars += String.fromCharCode(parseInt(dstHex.substr(c, 4), 16)); } map[srcCode] = uniChars; } } } } // 2. beginbfrange ... endbfrange var bfRangeMatches = cmapText.match(/\d+\s+beginbfrange([\s\S]*?)endbfrange/g); if (bfRangeMatches) { for (var r = 0; r < bfRangeMatches.length; r++) { var rLines = bfRangeMatches[r].split(/\r?\n/); for (var rl = 0; rl < rLines.length; rl++) { var range1 = rLines[rl].match(/<([0-9a-fA-F]+)>\s+<([0-9a-fA-F]+)>\s+<([0-9a-fA-F]+)>/); if (range1) { var startC = parseInt(range1[1], 16); var endC = parseInt(range1[2], 16); var startDst = parseInt(range1[3], 16); for (var code = startC; code <= endC; code++) { map[code] = String.fromCharCode(startDst + (code - startC)); } } } } } return map; }, // Resolve Page Fonts, ToUnicode CMaps and Widths specifically for Page N resolvePageFonts: function (pageHeader, objectMap) { var fontMap = {}; // fontTag -> { baseFont, cMap, widths, firstChar, lastChar, isToUnicodeValid } // Locate /Resources var resHeader = pageHeader; var resRefMatch = pageHeader.match(/\/Resources\s+(\d+)\s+(\d+)\s+R/); if (resRefMatch) { var resObjNum = parseInt(resRefMatch[1], 10); if (objectMap[resObjNum]) { resHeader = objectMap[resObjNum].header; } } // Find /Font << ... >> var fontBlockMatch = resHeader.match(/\/Font\s*<<([\s\S]*?)>>/); if (!fontBlockMatch) { var fontRefMatch = resHeader.match(/\/Font\s+(\d+)\s+(\d+)\s+R/); if (fontRefMatch && objectMap[parseInt(fontRefMatch[1], 10)]) { fontBlockMatch = objectMap[parseInt(fontRefMatch[1], 10)].header.match(/<<([\s\S]*?)>>/); } } if (fontBlockMatch) { var fontDictContent = fontBlockMatch[1]; var fontEntryRegex = /\/(\S+)\s+(\d+)\s+(\d+)\s+R/g; var fontEntry; while ((fontEntry = fontEntryRegex.exec(fontDictContent)) !== null) { var fontTag = fontEntry[1]; var fObjNum = parseInt(fontEntry[2], 10); if (objectMap[fObjNum]) { var fHeader = objectMap[fObjNum].header; var baseFontMatch = fHeader.match(/\/BaseFont\s*\/([^\s\/>]+)/); var baseFont = baseFontMatch ? baseFontMatch[1] : fontTag; // Check /ToUnicode var toUniMatch = fHeader.match(/\/ToUnicode\s+(\d+)\s+(\d+)\s+R/); var cMap = {}; var hasToUnicode = false; if (toUniMatch) { var toUniObjNum = parseInt(toUniMatch[1], 10); if (objectMap[toUniObjNum]) { var cmapStreamText = KeterPDFParser.decompressStream(objectMap[toUniObjNum]); cMap = KeterPDFParser.parseCMapText(cmapStreamText); hasToUnicode = KeterUtils.getKeyCount(cMap) > 0; } } // Check /Widths var widths = []; var firstChar = 0, lastChar = 255; var fcMatch = fHeader.match(/\/FirstChar\s+(\d+)/); var lcMatch = fHeader.match(/\/LastChar\s+(\d+)/); if (fcMatch) firstChar = parseInt(fcMatch[1], 10); if (lcMatch) lastChar = parseInt(lcMatch[1], 10); var wArrayMatch = fHeader.match(/\/Widths\s*\[([\s\S]*?)\]/); if (!wArrayMatch) { var wRefMatch = fHeader.match(/\/Widths\s+(\d+)\s+(\d+)\s+R/); if (wRefMatch && objectMap[parseInt(wRefMatch[1], 10)]) { wArrayMatch = objectMap[parseInt(wRefMatch[1], 10)].header.match(/\[([\s\S]*?)\]/); } } if (wArrayMatch) { var wParts = wArrayMatch[1].split(/\s+/); for (var wp = 0; wp < wParts.length; wp++) { if (wParts[wp] !== "") { widths.push(parseFloat(wParts[wp])); } } } fontMap[fontTag] = { baseFont: baseFont, cMap: cMap, hasToUnicode: hasToUnicode, widths: widths, firstChar: firstChar, lastChar: lastChar }; } } } return fontMap; }, // Decode PDF string using the specific font's CMap decodePDFString: function (str, fontInfo, isHex) { if (!str) return ""; var cMap = (fontInfo && fontInfo.cMap) ? fontInfo.cMap : null; var res = ""; if (isHex) { for (var i = 0; i < str.length; i += 4) { var hexCode = parseInt(str.substr(i, 4), 16); if (cMap && cMap[hexCode]) { res += cMap[hexCode]; } else if (hexCode >= 0x0590 && hexCode <= 0x05FF) { res += String.fromCharCode(hexCode); } else { var b1 = (hexCode >> 8) & 0xFF; var b2 = hexCode & 0xFF; if (b1 > 0) res += String.fromCharCode(b1); if (b2 > 0) res += String.fromCharCode(b2); } } } else { var unescaped = str .replace(/\\n/g, "\n") .replace(/\\r/g, "\r") .replace(/\\t/g, "\t") .replace(/\\\(/g, "(") .replace(/\\\)/g, ")") .replace(/\\\\/g, "\\"); for (var j = 0; j < unescaped.length; j++) { var chCode = unescaped.charCodeAt(j); if (cMap && cMap[chCode]) { res += cMap[chCode]; } else { res += unescaped.charAt(j); } } } return res; }, // Calculate string width using font /Widths metrics when available calculateSpanWidth: function (textStr, fontSize, fontInfo) { if (fontInfo && fontInfo.widths && fontInfo.widths.length > 0) { var totalPt = 0; for (var i = 0; i < textStr.length; i++) { var code = textStr.charCodeAt(i); var idx = code - fontInfo.firstChar; if (idx >= 0 && idx < fontInfo.widths.length) { totalPt += (fontInfo.widths[idx] / 1000.0) * fontSize; } else { totalPt += fontSize * 0.55; // measured fallback } } return { widthPt: totalPt, isMeasured: true }; } // If no /Widths table exists in font descriptor, return flag for uncertain geometry return { widthPt: textStr.length * (fontSize * 0.55), isMeasured: false }; }, // Extract positioned text spans from decompressed content stream of a single page extractPageTextSpans: function (contentStreamText, pageFonts, pageHeightPt) { var spans = []; var textBlockRegex = /BT[\s\S]*?ET/g; var blockMatch; while ((blockMatch = textBlockRegex.exec(contentStreamText)) !== null) { var block = blockMatch[0]; var curFontTag = "Default"; var curSize = 10; var curX = 0, curY = 0; var leading = 12; var ops = block.split(/\r?\n/); for (var i = 0; i < ops.length; i++) { var line = ops[i]; // Font selection: /F1 12 Tf var tfMatch = line.match(/\/(\S+)\s+([\d\.\-]+)\s+Tf/); if (tfMatch) { curFontTag = tfMatch[1]; curSize = parseFloat(tfMatch[2]); continue; } // Text matrix: [a b c d e f] Tm var tmMatch = line.match(/([\d\.\-]+)\s+([\d\.\-]+)\s+([\d\.\-]+)\s+([\d\.\-]+)\s+([\d\.\-]+)\s+([\d\.\-]+)\s+Tm/); if (tmMatch) { curX = parseFloat(tmMatch[5]); curY = parseFloat(tmMatch[6]); continue; } // Text position: x y Td or TD var tdMatch = line.match(/([\d\.\-]+)\s+([\d\.\-]+)\s+T[dD]/); if (tdMatch) { curX += parseFloat(tdMatch[1]); curY += parseFloat(tdMatch[2]); continue; } // Set leading: TL var tlMatch = line.match(/([\d\.\-]+)\s+TL/); if (tlMatch) { leading = parseFloat(tlMatch[1]); continue; } // Move to next line: T* if (line.match(/T\*/)) { curY -= leading; continue; } // Show text: (string) Tj or <hex> Tj var tjMatch = line.match(/\(([\s\S]*?)\)\s*Tj/) || line.match(/<([0-9a-fA-F]+)>\s*Tj/); if (tjMatch) { var rawText = tjMatch[1]; var fontInfo = pageFonts[curFontTag]; var decoded = KeterPDFParser.decodePDFString(rawText, fontInfo, line.indexOf("<") !== -1); if (decoded && decoded.length > 0) { var wResult = KeterPDFParser.calculateSpanWidth(decoded, curSize, fontInfo); var idTop = pageHeightPt - curY - curSize; spans.push({ text: decoded, x: curX, y: idTop, fontSize: curSize, fontTag: curFontTag, baseFont: fontInfo ? fontInfo.baseFont : "Unknown", width: wResult.widthPt, isMeasuredWidth: wResult.isMeasured, height: curSize * 1.2 }); curX += wResult.widthPt; } continue; } // Show text array: [ (str) 20 (str) ] TJ var bigTjMatch = line.match(/\[([\s\S]*?)\]\s*TJ/); if (bigTjMatch) { var arrayContent = bigTjMatch[1]; var fontInfo2 = pageFonts[curFontTag]; var elemRegex = /\(([\s\S]*?)\)|<([0-9a-fA-F]+)>|([\d\.\-]+)/g; var elemMatch; var chunkText = ""; var chunkWidth = 0; while ((elemMatch = elemRegex.exec(arrayContent)) !== null) { if (elemMatch[1] || elemMatch[2]) { var itemRaw = elemMatch[1] || elemMatch[2]; var isHex = !!elemMatch[2]; var dStr = KeterPDFParser.decodePDFString(itemRaw, fontInfo2, isHex); chunkText += dStr; var wSub = KeterPDFParser.calculateSpanWidth(dStr, curSize, fontInfo2); chunkWidth += wSub.widthPt; } else if (elemMatch[3]) { // Kerning adjustment in 1/1000 text units var kernVal = parseFloat(elemMatch[3]); chunkWidth -= (kernVal / 1000.0) * curSize; } } if (chunkText && chunkText.length > 0) { var idTop2 = pageHeightPt - curY - curSize; spans.push({ text: chunkText, x: curX, y: idTop2, fontSize: curSize, fontTag: curFontTag, baseFont: fontInfo2 ? fontInfo2.baseFont : "Unknown", width: chunkWidth, isMeasuredWidth: !!(fontInfo2 && fontInfo2.widths && fontInfo2.widths.length > 0), height: curSize * 1.2 }); curX += chunkWidth; } } } } return spans; } }; // ------------------------------------------------------------------------ // MODULE 6: SPATIAL LAYOUT & PHYSICAL GUTTER ANALYSIS (NO ARBITRARY %) // ------------------------------------------------------------------------ var KeterLayoutEngine = { // Groups raw text spans into lines and detects physical column gutters analyzeLayout: function (spans, pageWidthPt, pageHeightPt) { if (!spans || spans.length === 0) return []; // 1. Sort spans: Top-to-Bottom, then Right-to-Left (for Hebrew) spans.sort(function (a, b) { var yDiff = a.y - b.y; if (Math.abs(yDiff) > 3.5) { return yDiff; } return b.x - a.x; // Right-to-Left }); // 2. Assemble into visual lines var lines = []; var curLine = null; for (var i = 0; i < spans.length; i++) { var s = spans[i]; if (!curLine || Math.abs(s.y - curLine.y) > (s.fontSize * 0.45)) { curLine = { y: s.y, fontSize: s.fontSize, minX: s.x, maxX: s.x + s.width, spans: [s], text: s.text }; lines.push(curLine); } else { curLine.spans.push(s); curLine.minX = Math.min(curLine.minX, s.x); curLine.maxX = Math.max(curLine.maxX, s.x + s.width); curLine.text += " " + s.text; } } // 3. Detect Headers & Footers based on vertical margins var headerLines = []; var footerLines = []; var candidateBodyLines = []; var topMarginBoundary = pageHeightPt * 0.10; var bottomMarginBoundary = pageHeightPt * 0.90; for (var l = 0; l < lines.length; l++) { var line = lines[l]; if (line.y < topMarginBoundary && line.fontSize <= 12) { headerLines.push(line); } else if (line.y > bottomMarginBoundary && line.fontSize <= 11) { footerLines.push(line); } else { candidateBodyLines.push(line); } } var regions = []; if (headerLines.length > 0) { regions.push(this.buildRegion(headerLines, "RunningHeader", "Keter_RunningHeader")); } // 4. Physical Gutter Analysis for Body Columns (not fixed arbitrary percentages) var columnRegions = this.detectPhysicalColumns(candidateBodyLines, pageWidthPt); for (var c = 0; c < columnRegions.length; c++) { regions.push(columnRegions[c]); } if (footerLines.length > 0) { regions.push(this.buildRegion(footerLines, "PageFooter", "Keter_RunningHeader")); } return regions; }, // Analyzes horizontal gaps between lines to detect true columns detectPhysicalColumns: function (bodyLines, pageWidthPt) { if (!bodyLines || bodyLines.length === 0) return []; // Calculate horizontal span frequencies var leftColumnLines = []; var rightColumnLines = []; var fullWidthLines = []; var midX = pageWidthPt / 2.0; var minGutterWidth = 14.0; // at least 14pt gutter between columns var hasLeft = false; var hasRight = false; for (var i = 0; i < bodyLines.length; i++) { var bl = bodyLines[i]; var width = bl.maxX - bl.minX; // If a line spans more than 70% of the page, it is a single-column or banner if (width > pageWidthPt * 0.70) { fullWidthLines.push(bl); } else if (bl.minX > (midX - 10)) { // Right column (RTL start) rightColumnLines.push(bl); hasRight = true; } else if (bl.maxX < (midX + 10)) { // Left column leftColumnLines.push(bl); hasLeft = true; } else { fullWidthLines.push(bl); } } var resultRegions = []; // If genuine dual columns are detected if (hasLeft && hasRight && (leftColumnLines.length + rightColumnLines.length > fullWidthLines.length)) { KeterLogger.log("Physical column gutter detected at X ≈ " + Math.round(midX) + " pt."); // Right-to-Left order: Right column first, then Left column if (rightColumnLines.length > 0) { resultRegions.push(this.buildRegion(rightColumnLines, "Column_Right_RTL", "Keter_Main_Hebrew_RTL")); } if (leftColumnLines.length > 0) { resultRegions.push(this.buildRegion(leftColumnLines, "Column_Left_RTL", "Keter_Main_Hebrew_RTL")); } if (fullWidthLines.length > 0) { resultRegions.push(this.buildRegion(fullWidthLines, "Body_Spanning", "Keter_Main_Hebrew_RTL")); } } else { // Single unified text stream resultRegions.push(this.buildRegion(bodyLines, "BodyText", "Keter_Main_Hebrew_RTL")); } return resultRegions; }, buildRegion: function (linesList, roleName, styleName) { var minY = 999999, minX = 999999, maxY = 0, maxX = 0; var textParts = []; for (var i = 0; i < linesList.length; i++) { var l = linesList[i]; minY = Math.min(minY, l.y); minX = Math.min(minX, l.minX); maxY = Math.max(maxY, l.y + (l.fontSize * 1.25)); maxX = Math.max(maxX, l.maxX); textParts.push(l.text); } return { role: roleName, styleName: styleName, bounds: [minY, minX, maxY, maxX], content: textParts.join("\r") }; } }; // ------------------------------------------------------------------------ // MODULE 7: INDESIGN DOM GENERATOR (VALIDATED API ACCESS) // ------------------------------------------------------------------------ var KeterInDesignDOM = { setupDocument: function (templateFile, pageWidthPt, pageHeightPt) { var doc; if (templateFile && templateFile.exists) { KeterLogger.log("Opening existing template: " + templateFile.fsName); doc = app.open(templateFile); } else { KeterLogger.log("Creating new InDesign document: " + Math.round(pageWidthPt) + " x " + Math.round(pageHeightPt) + " pt"); doc = app.documents.add(); doc.documentPreferences.pageWidth = pageWidthPt + "pt"; doc.documentPreferences.pageHeight = pageHeightPt + "pt"; doc.documentPreferences.facingPages = true; } // CRITICAL FIX: Explicitly lock document measurement units to Points // to prevent coordinate scaling errors when user InDesign uses mm or picas try { doc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.POINTS; doc.viewPreferences.verticalMeasurementUnits = MeasurementUnits.POINTS; doc.viewPreferences.rulerOrigin = RulerOrigin.PAGE_ORIGIN; } catch (eUnits) { KeterLogger.warn("Measurement unit assignment warning: " + eUnits.message); } this.ensureLayers(doc); this.ensureStyles(doc); return doc; }, ensureLayers: function (doc) { // PDF Reference Underlay (locked, bottom) var underlayLayer = doc.layers.itemByName(KeterConfig.layerUnderlay); if (!underlayLayer.isValid) { // UIColors safety check: never reference bare UIColors underlayLayer = doc.layers.add({ name: KeterConfig.layerUnderlay }); } underlayLayer.move(LocationOptions.AT_END); // Reconstructed Editable Text (active, top) var textLayer = doc.layers.itemByName(KeterConfig.layerText); if (!textLayer.isValid) { textLayer = doc.layers.add({ name: KeterConfig.layerText }); } doc.activeLayer = textLayer; }, ensureStyles: function (doc) { var bestHebrewFont = this.findBestAvailableFont(KeterConfig.hebrewFontFallbacks); KeterLogger.log("Selected primary Hebrew font: " + bestHebrewFont); this.createOrUpdateParaStyle(doc, "Keter_Main_Hebrew_RTL", { appliedFont: bestHebrewFont, pointSize: 12, leading: 15.5, justification: Justification.FULLY_JUSTIFIED, isRTL: true }); this.createOrUpdateParaStyle(doc, "Keter_RunningHeader", { appliedFont: bestHebrewFont, pointSize: 9, leading: 11, justification: Justification.CENTER_ALIGN, isRTL: true }); }, findBestAvailableFont: function (candidates) { for (var i = 0; i < candidates.length; i++) { var candidate = candidates[i]; try { var f = app.fonts.itemByName(candidate); if (f && f.isValid) { return candidate; } } catch (e) {} } KeterLogger.stats.fontSubstitutions.push("Times New Roman (Hebrew fallback)"); return "Times New Roman"; }, createOrUpdateParaStyle: function (doc, styleName, props) { var style = doc.paragraphStyles.itemByName(styleName); if (!style.isValid) { style = doc.paragraphStyles.add({ name: styleName }); } try { if (props.appliedFont) style.appliedFont = props.appliedFont; if (props.pointSize) style.pointSize = props.pointSize; if (props.leading) style.leading = props.leading; if (props.justification) style.justification = props.justification; // Enforce Adobe World-Ready Paragraph Composer try { style.composer = "Adobe World-Ready Paragraph Composer"; } catch (e1) { try { style.composer = "$ID/Adobe World-Ready Paragraph Composer"; } catch (e2) {} } // Enforce Right-to-Left Direction if (props.isRTL) { try { style.paragraphDirection = ParagraphDirectionOptions.RIGHT_TO_LEFT_DIRECTION; } catch (e3) { try { style.paragraphDirection = 1278366308; } catch (e4) {} } } } catch (ex) { KeterLogger.warn("Style configuration note for '" + styleName + "': " + ex.message); } return style; }, placePDFUnderlay: function (doc, page, pdfFile, pageNum, opacity) { try { var underlayLayer = doc.layers.itemByName(KeterConfig.layerUnderlay); underlayLayer.locked = false; doc.activeLayer = underlayLayer; try { app.pdfPlacePreferences.pdfCrop = PDFCrop.CROP_MEDIA; } catch (eCrop) { try { app.pdfPlacePreferences.pdfCrop = PDFCrop.cropMedia; } catch (eCrop2) {} } app.pdfPlacePreferences.pageNumber = pageNum; app.pdfPlacePreferences.transparentBackground = true; var placed = page.place(pdfFile, [0, 0])[0]; if (placed && placed.isValid && opacity && opacity < 100) { try { placed.transparencySettings.blendingSettings.opacity = opacity; } catch (eOp) {} } underlayLayer.locked = true; doc.activeLayer = doc.layers.itemByName(KeterConfig.layerText); KeterLogger.log("Placed 1:1 PDF underlay reference for page " + pageNum); return true; } catch (ex) { KeterLogger.error("Failed to place PDF underlay for page " + pageNum + ": " + ex.message); return false; } }, createTextFrame: function (doc, page, bounds, content, styleName) { try { var textLayer = doc.layers.itemByName(KeterConfig.layerText); doc.activeLayer = textLayer; var top = Math.max(0, bounds[0]); var left = Math.max(0, bounds[1]); var bottom = Math.max(top + 16, bounds[2]); var right = Math.max(left + 24, bounds[3]); var frame = page.textFrames.add(textLayer, LocationOptions.UNKNOWN_VALUE, { geometricBounds: [top, left, bottom, right] }); // Apply World-Ready Composer directly to frame parent story try { frame.parentStory.composer = "Adobe World-Ready Paragraph Composer"; frame.parentStory.paragraphDirection = ParagraphDirectionOptions.RIGHT_TO_LEFT_DIRECTION; } catch (eWRC) {} // Assign Unicode text contents frame.contents = content; var pStyle = doc.paragraphStyles.itemByName(styleName); if (pStyle.isValid) { frame.parentStory.texts.item(0).applyParagraphStyle(pStyle, true); } KeterLogger.stats.textFramesCreated++; KeterLogger.stats.charactersExtracted += content.length; if (frame.overflows) { KeterLogger.stats.oversetFrames++; KeterLogger.warn("Overset text in frame on page " + page.name + " (" + styleName + "). Frame resized slightly or leading adjustment required."); } return frame; } catch (ex) { KeterLogger.error("Error creating InDesign text frame: " + ex.message); return null; } } }; // ------------------------------------------------------------------------ // MODULE 8: USER INTERFACE (SCRIPTUI DIALOG & PROGRESS WINDOW) // ------------------------------------------------------------------------ var KeterUI = { showMainDialog: function () { var w = new Window("dialog", KeterConfig.name + " v" + KeterConfig.version); w.orientation = "column"; w.alignChildren = ["fill", "top"]; w.spacing = 10; w.margins = 16; var headerPnl = w.add("panel", undefined, undefined, { borderStyle: "black" }); headerPnl.orientation = "column"; headerPnl.alignChildren = ["fill", "top"]; headerPnl.margins = 10; var titleTxt = headerPnl.add("statictext", undefined, "KETER PDF-TO-INDESIGN CONVERSION ENGINE"); titleTxt.graphics.font = ScriptUI.newFont(w.graphics.font.name, ScriptUI.FontStyle.BOLD, 14); headerPnl.add("statictext", undefined, "Audited Production Engine: Strict Truth-in-Extraction Architecture"); // SOURCE PDF var srcPnl = w.add("panel", undefined, "Source PDF & Options"); srcPnl.orientation = "column"; srcPnl.alignChildren = ["fill", "top"]; srcPnl.margins = 12; srcPnl.spacing = 8; var pdfRow = srcPnl.add("group"); pdfRow.orientation = "row"; var pdfPathInput = pdfRow.add("edittext", undefined, "", { readonly: true }); pdfPathInput.characters = 42; var browsePdfBtn = pdfRow.add("button", undefined, "Browse PDF..."); var pdfInfoTxt = srcPnl.add("statictext", undefined, "Select a PDF to inspect structure and content streams."); var optGroup = srcPnl.add("group"); optGroup.orientation = "column"; optGroup.alignChildren = ["left", "top"]; optGroup.spacing = 4; var underlayCb = optGroup.add("checkbox", undefined, "Place original PDF page as locked 1:1 visual reference underlay"); underlayCb.value = true; var opacityRow = optGroup.add("group"); opacityRow.orientation = "row"; opacityRow.add("statictext", undefined, "Underlay Opacity:"); var opacityDropdown = opacityRow.add("dropdownlist", undefined, ["25%", "40% (Recommended)", "60%", "100% (Solid)"]); opacityDropdown.selection = 1; var pageRangeRow = srcPnl.add("group"); pageRangeRow.orientation = "row"; pageRangeRow.add("statictext", undefined, "Page Range to Process:"); var pageRangeInput = pageRangeRow.add("edittext", undefined, "All"); pageRangeInput.characters = 12; pageRangeRow.add("statictext", undefined, "(e.g., 'All', '1-5')"); var btnRow = w.add("group"); btnRow.orientation = "row"; btnRow.alignment = "right"; var cancelBtn = btnRow.add("button", undefined, "Cancel", { name: "cancel" }); var convertBtn = btnRow.add("button", undefined, "Start Conversion", { name: "ok" }); convertBtn.enabled = false; var selectedFile = null; browsePdfBtn.onClick = function () { var f = File.openDialog("Select Source PDF File", "PDF Files:*.pdf;All Files:*.*"); if (f) { selectedFile = f; pdfPathInput.text = f.fsName; pdfInfoTxt.text = "Inspecting PDF: " + f.name + "..."; convertBtn.enabled = true; } }; if (w.show() === 1) { var opacityVal = 40; if (opacityDropdown.selection.index === 0) opacityVal = 25; if (opacityDropdown.selection.index === 1) opacityVal = 40; if (opacityDropdown.selection.index === 2) opacityVal = 60; if (opacityDropdown.selection.index === 3) opacityVal = 100; return { pdfFile: selectedFile, placeUnderlay: underlayCb.value, underlayOpacity: opacityVal, pageRange: pageRangeInput.text }; } return null; }, showProgress: function (title, maxVal) { var pw = new Window("palette", title); pw.orientation = "column"; pw.alignChildren = ["fill", "top"]; pw.margins = 16; pw.spacing = 10; var statusTxt = pw.add("statictext", undefined, "Initializing conversion pipeline..."); statusTxt.characters = 45; var pBar = pw.add("progressbar", undefined, 0, maxVal); pBar.preferredSize.width = 320; pw.center(); pw.show(); return { update: function (val, text) { pBar.value = val; if (text) statusTxt.text = text; pw.update(); }, close: function () { pw.close(); } }; } }; // ------------------------------------------------------------------------ // MODULE 9: CONVERSION PIPELINE (STRICT & HONEST EXTRACTION) // ------------------------------------------------------------------------ function parsePageRange(rangeStr, totalPages) { var pages = []; if (!rangeStr || rangeStr.toLowerCase() === "all") { for (var i = 1; i <= totalPages; i++) pages.push(i); return pages; } var parts = rangeStr.split(","); for (var p = 0; p < parts.length; p++) { var part = KeterUtils.trim(parts[p]); if (part.indexOf("-") !== -1) { var range = part.split("-"); var start = parseInt(range[0], 10); var end = parseInt(range[1], 10); if (!isNaN(start) && !isNaN(end)) { for (var r = start; r <= Math.min(end, totalPages); r++) { pages.push(r); } } } else { var single = parseInt(part, 10); if (!isNaN(single) && single >= 1 && single <= totalPages) { pages.push(single); } } } return pages.length > 0 ? pages : [1]; } function runConversion(options) { KeterLogger.log("Starting Keter conversion: " + options.pdfFile.fsName); // 1. Read binary bytes and raw string var bytes = KeterPDFParser.readFileBytes(options.pdfFile); var rawStr = KeterPDFParser.bytesToString(bytes); // 2. Index PDF objects var objectMap = KeterPDFParser.indexPDFObjects(rawStr, bytes); var totalObjects = KeterUtils.getKeyCount(objectMap); KeterLogger.log("Indexed " + totalObjects + " indirect PDF objects."); // 3. Locate Root Catalog & Pages Tree var catalogObjNum = null; var pagesObjNum = null; var rootMatch = rawStr.match(/\/Root\s+(\d+)\s+(\d+)\s+R/); if (rootMatch) { catalogObjNum = parseInt(rootMatch[1], 10); if (objectMap[catalogObjNum]) { var catHeader = objectMap[catalogObjNum].header; var pagesMatch = catHeader.match(/\/Pages\s+(\d+)\s+(\d+)\s+R/); if (pagesMatch) { pagesObjNum = parseInt(pagesMatch[1], 10); } } } // Fallback: search for /Type /Pages object if (!pagesObjNum) { for (var objId in objectMap) { if (objectMap[objId].header.indexOf("/Type /Pages") !== -1 || objectMap[objId].header.indexOf("/Type/Pages") !== -1) { pagesObjNum = parseInt(objId, 10); break; } } } // 4. Resolve Page Objects through Pages Tree var resolvedPages = []; if (pagesObjNum) { KeterPDFParser.resolvePageTree(pagesObjNum, objectMap, resolvedPages, {}, null); } var totalPages = resolvedPages.length; if (totalPages === 0) { // Scan /Type /Page directly if Pages tree was obfuscated for (var pId in objectMap) { if (objectMap[pId].header.indexOf("/Type /Page") !== -1 || objectMap[pId].header.indexOf("/Type/Page") !== -1) { resolvedPages.push({ pageObjNum: parseInt(pId, 10), mediaBox: [0, 0, 595.28, 841.89], header: objectMap[pId].header }); } } totalPages = resolvedPages.length; } if (totalPages === 0) { totalPages = 1; } KeterLogger.reset(totalPages); KeterLogger.log("Resolved " + totalPages + " pages from PDF object graph."); var targetPages = parsePageRange(options.pageRange, totalPages); var progress = KeterUI.showProgress("Reconstructing InDesign Document", targetPages.length + 2); progress.update(0, "Setting up InDesign document & World-Ready styles..."); // 5. Establish InDesign Document matching initial page geometry var initialMediaBox = (resolvedPages.length > 0 && resolvedPages[0].mediaBox) ? resolvedPages[0].mediaBox : [0, 0, 595.28, 841.89]; var pageWidthPt = Math.abs(initialMediaBox[2] - initialMediaBox[0]); var pageHeightPt = Math.abs(initialMediaBox[3] - initialMediaBox[1]); var doc = KeterInDesignDOM.setupDocument(null, pageWidthPt, pageHeightPt); while (doc.pages.length < targetPages.length) { doc.pages.add(LocationOptions.AT_END); } // 6. Process each selected page for (var pIdx = 0; pIdx < targetPages.length; pIdx++) { var pageNum = targetPages[pIdx]; var idPage = doc.pages[pIdx]; progress.update(pIdx + 1, "Processing Page " + pageNum + " of " + targetPages.length + "..."); // Always place PDF 1:1 visual reference underlay when requested if (options.placeUnderlay) { KeterInDesignDOM.placePDFUnderlay(doc, idPage, options.pdfFile, pageNum, options.underlayOpacity); } var pageMeta = (pageNum - 1 < resolvedPages.length) ? resolvedPages[pageNum - 1] : null; if (!pageMeta) { KeterLogger.recordPageAudit( pageNum, "REFERENCE_UNDERLAY_ONLY", "Page structure could not be resolved from object tree. Visual underlay placed.", 0, 0 ); continue; } // Extract page /Contents object(s) var contentsMatches = []; var cRefRegex = /\/Contents\s+(\d+)\s+(\d+)\s+R/g; var cMatch; while ((cMatch = cRefRegex.exec(pageMeta.header)) !== null) { contentsMatches.push(parseInt(cMatch[1], 10)); } // Also check for /Contents [ 12 0 R 13 0 R ] var cArrayMatch = pageMeta.header.match(/\/Contents\s*\[([\s\S]*?)\]/); if (cArrayMatch) { var cArrRefs = cArrayMatch[1].match(/(\d+)\s+(\d+)\s+R/g); if (cArrRefs) { for (var cr = 0; cr < cArrRefs.length; cr++) { var idNum = parseInt(cArrRefs[cr].split(/\s+/)[0], 10); if (!KeterUtils.arrayContains(contentsMatches, idNum)) { contentsMatches.push(idNum); } } } } // If no contents objects could be located if (contentsMatches.length === 0) { KeterLogger.recordPageAudit( pageNum, "REFERENCE_UNDERLAY_ONLY", "No /Contents stream found (Page may be scanned raster image or use ObjStm). Visual underlay preserved.", 0, 0 ); continue; } // Concatenate all content streams for this page var pageContentText = ""; for (var cIdx = 0; cIdx < contentsMatches.length; cIdx++) { var cObjNum = contentsMatches[cIdx]; if (objectMap[cObjNum]) { pageContentText += KeterPDFParser.decompressStream(objectMap[cObjNum]) + "\n"; } } // Check if content stream has any text operators (BT...ET) if (pageContentText.indexOf("BT") === -1 || pageContentText.indexOf("ET") === -1) { KeterLogger.recordPageAudit( pageNum, "REFERENCE_UNDERLAY_ONLY", "Content stream contains vector/raster artwork only (no text operators BT...ET). Visual underlay preserved.", 0, 0 ); continue; } // Resolve page-specific fonts and ToUnicode CMaps var pageFonts = KeterPDFParser.resolvePageFonts(pageMeta.header, objectMap); // Extract text spans var curPageHeightPt = Math.abs(pageMeta.mediaBox[3] - pageMeta.mediaBox[1]); var curPageWidthPt = Math.abs(pageMeta.mediaBox[2] - pageMeta.mediaBox[0]); var spans = KeterPDFParser.extractPageTextSpans(pageContentText, pageFonts, curPageHeightPt); if (spans.length === 0) { KeterLogger.recordPageAudit( pageNum, "REFERENCE_UNDERLAY_ONLY", "Text operators could not be mapped to Unicode characters (Font encodings / ToUnicode missing). Visual underlay preserved.", 0, 0 ); continue; } // Gutter and layout analysis var regions = KeterLayoutEngine.analyzeLayout(spans, curPageWidthPt, curPageHeightPt); // Create editable InDesign Text Frames var pageCharCount = 0; for (var r = 0; r < regions.length; r++) { var reg = regions[r]; KeterInDesignDOM.createTextFrame(doc, idPage, reg.bounds, reg.content, reg.styleName); pageCharCount += reg.content.length; } KeterLogger.recordPageAudit( pageNum, "EDITABLE_RECONSTRUCTED", "Successfully reconstructed " + regions.length + " editable text frame(s).", regions.length, pageCharCount ); } progress.update(targetPages.length + 1, "Saving diagnostic report..."); progress.close(); // 7. Save Audit Report var folder = options.pdfFile.parent; var baseName = options.pdfFile.name.replace(/\.pdf$/i, ""); var reportFile = KeterLogger.saveReportFile(folder.fsName, baseName, doc.name, options.pdfFile.fsName); // 8. Display Completion Summary Dialog var summaryMsg = "Keter Conversion Completed!\n\n" + "• Total Pages Processed: " + targetPages.length + "\n" + "• Pages Converted to Editable Text: " + KeterLogger.stats.editablePagesCount + "\n" + "• Pages Preserved as 1:1 Visual Underlay: " + KeterLogger.stats.underlayOnlyPagesCount + "\n" + "• Text Frames Created: " + KeterLogger.stats.textFramesCreated + "\n" + "• Recovered Characters: " + KeterLogger.stats.charactersExtracted + "\n" + "• Overset Text Warnings: " + KeterLogger.stats.oversetFrames + "\n\n" + "Diagnostic report saved to:\n" + (reportFile ? reportFile.fsName : "Report generated in log."); alert(summaryMsg, KeterConfig.name); } // ------------------------------------------------------------------------ // ENTRY POINT: SINGLE UNDOABLE TRANSACTION // ------------------------------------------------------------------------ function main() { if (typeof app === "undefined" || app.documents === undefined) { alert("This script must be run directly inside Adobe InDesign.", "Keter Engine Error"); return; } var options = KeterUI.showMainDialog(); if (!options) return; app.doScript( function () { try { runConversion(options); } catch (err) { alert("Conversion encountered a critical error:\n" + err.message + "\nLine: " + (err.line || "unknown"), "Keter Error"); KeterLogger.error("CRITICAL RUNTIME ERROR: " + err.message + " (Line " + (err.line || "unknown") + ")"); } }, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Keter PDF to InDesign Conversion" ); } main(); })();
  • 1k נושאים
    16k פוסטים
    ח
    @אלכסנדר-צדש מה מצאת ?
  • 242 נושאים
    4k פוסטים
    4
    @ההוא-שאמר על פי חוקי הפורום אסור להקפיץ נושא ישן
  • שאלות רעיונות תוספים ודרך עבודה עם אמולטורים שונים לאנדרואיד

    265 4k
    265 נושאים
    4k פוסטים
    25802
    @zzzzzzzz תחפש מתקין XAPK תוריד ותתקין דרכו https://send.magicode.me/*****send-file/file/4847f77dd302c3346cf9d100a23b438c10966dde/view
  • בקשות ודיונים על כלי נגינה בפן הטכני שבו

    0 0
    0 נושאים
    0 פוסטים
    אין פוסטים חדשים.
  • 18 הצבעות
    33 פוסטים
    3k צפיות
    I
    @יעקב11 תודה רבה על התוכנה, היא פשוט מדהימה ואפקטיבית מאוד. 2 הערות- אם פותחים את הקובץ בדפדפן אגד' ומעדכנים נתונים, ואחר כך פותחים אותו בדפדפן כרום הנתונים לא קיימים, מה שאומר שהנתונים נראים רק בפלטפורמה דרכה הוזנו, אין לי בעיה עם זה רק שזו נקודה שכדאי לשים לב אליה. כפי שכתבו כאן קודם, כדאי להוסיף בכל עדכון שדה נוסף להזנת כל תוספת תשלום שהיא, כלומר, סכום שיוזן באופן חופשי, כגון תשלום קבוע תשלום בגין הספק ותשלומי ריבית. ושוב תודה רבה
  • באג | כתב הפוך בעורך תמונות וינדוס

    1
    1
    0 הצבעות
    1 פוסטים
    278 צפיות
    אין תגובות
  • עזרה | עזרה בהתקנת אוטוקד

    3
    1
    0 הצבעות
    3 פוסטים
    397 צפיות
    י
    @יאנג-בוי מה עושים עכשיו? [image: 1741689094591-287693c8-5418-4044-9a1e-074379bdda47-image.png]
  • המלצה | מעניין - כשגמיני כותב שהוא חושב ויעלה תשובה בהמשך

    6
    2 הצבעות
    6 פוסטים
    639 צפיות
    א
    הסברתי לך, הוא לא באמת חושב. הוא עושה עליך הצגה. אם היית שואל אותו נניח עשרה פעמים ברצף אם ישנה התקדמות, הוא היה מספק את התשובה.
  • באג | תוכנת OSSIA VMS של פרוויזון לא מצליח להתקין על מחשב

    6
    1
    0 הצבעות
    6 פוסטים
    539 צפיות
    א
    @מיכאלוש תודה רבה זה מה שאכן עזר
  • בקשה | להמיר את התוכנה של קיוליקס לתוכנה ניידת

    10
    0 הצבעות
    10 פוסטים
    733 צפיות
    D
    @מישהו12 כתב בבקשה | להמיר את התוכנה של קיוליקס לתוכנה ניידת: @פלמנמוני כתב בבקשה | להמיר את התוכנה של קיוליקס לתוכנה ניידת: לגבי הדרייברים אני משער שזה לא יהיה בעיה ודאי שכן. דרייברים צריכים להיות מותקנים על המחשב עצמו. נכון, אבל אפשר להריץ קובץ התקנה שלהם בכל פעם מחדש
  • בקשה | פריצת תוכנה

    6
    0 הצבעות
    6 פוסטים
    659 צפיות
    פלמנמוניפ
    @אם-לא-עכשיו כתב בבקשה | פריצת תוכנה: דוד יצחק: כמו שכתב פלמנמוני שניהם חסומים בנטפרי. אם יש לך אפשרות להעלות לכאן את הקובץ תבורך. Spoiler לתיוג מוצלח יש לשים @ לפני שם המשתמש וכמו כן להשים - במקום רווח בין שני המילים של שם המשתמש
  • בעיה | פרוייקט באוטוקאד לא נפתח

    3
    2
    0 הצבעות
    3 פוסטים
    376 צפיות
    אביב לויןא
    @רפאל-0 fix_autoCad.rar קיבלתי לאחרונה פה בפורום, לא זוכר איפה, תבדוק אם עובד
  • להורדה | SoftwarePolicy - תוכנה לחסימת קבצים לפי סיומות.

    25
    2
    13 הצבעות
    25 פוסטים
    3k צפיות
    פלמנמוניפ
    @למה-מה-קרה יפה מאוד, מוצלח ביותר!!! רק כדאי להדגיש בתחילת השרשור את הדברים הבאים: @למה-מה-קרה כתב בלהורדה | SoftwarePolicy - תוכנה לחסימת קבצים לפי סיומות.: אז אני מסיר מהמחשב כל תוכנה שיכולה להריץ קובץ וידאו @פלמנמוני כתב בלהורדה | SoftwarePolicy - תוכנה לחסימת קבצים לפי סיומות.: גם דפדפן... אז אל תשכח להתקין תוכנה ל PDF... @למה-מה-קרה כתב בלהורדה | SoftwarePolicy - תוכנה לחסימת קבצים לפי סיומות.: אז ברור שבשביל זה אני נועל את הבוט וסוגר את הביוס וכו', @פלמנמוני כתב בלהורדה | SoftwarePolicy - תוכנה לחסימת קבצים לפי סיומות.: אלא א"כ אני לא מנהל
  • בקשת מידע | IVMS-4200 עזרה

    1
    0 הצבעות
    1 פוסטים
    187 צפיות
    אין תגובות
  • 1 הצבעות
    2 פוסטים
    643 צפיות
    יעקב ישראלי
    המחיר ירד כי התחלתי להתעסק עם זה בצורה קבועה מי שמעוניין מוזמן לפנות
  • נושא זה נמחק!

    52
    0 הצבעות
    52 פוסטים
    320 צפיות
  • בעיה | שגיאה בהתקנת JAVA

    3
    1 הצבעות
    3 פוסטים
    352 צפיות
    מ
    @צבי-מחשבים תודה רבה!
  • מדריך | אפלקציית הגרלות למחשב באמצעות פקודות מאקרו בוורד

    3
    4 הצבעות
    3 פוסטים
    503 צפיות
    S
    @פלמנמוני התשובה אקראית לחלוטין להכניס לקובץ וורד שייך א"י הסדרן בפקודות מאקרו ולהעתיק את שני הדברים שבתוך הקובץ הזה ל normal
  • 0 הצבעות
    4 פוסטים
    494 צפיות
    שאול 208ש
    @haimil מתקינים כל סוג של אמולטור, אני ספציפית אוהב ממש את נוקס וגם כתבתי עליו מדריך איך להתקין אותו בנוסף אתה יכול להוריד, נגיד מכאן את האפליקציות שאתה מעוניין בהם בקובץ APK (של אפליקציות) ולגרור אותן למסך הבית של האמולטור ואז הן מותקנות.
  • בקשת מידע | תוכנה ליצירת פלייבקים

    3
    -1 הצבעות
    3 פוסטים
    460 צפיות
    אביעדא
    https://mitmachim.top/topic/41322/מדריך-כיצד-תעשו-פליבק-קריוקי-כל-השיטות?_=1736800615922 Spoiler אני לא ישקר שמכל השיטות שניסתי הכי הייתי מרוצה ממה שאני הבאתי שם
  • להורדה | המרת טקסט מעברית לתווי יוניקוד, וכן הפוך

    3
    3 הצבעות
    3 פוסטים
    593 צפיות
    יום חדש מתחילי
    עדכנתי את הסקריפט לממשק חדש, עם כמה שיפורים, וכן נוסף סקריפט חדש להורדה בהודעה הראשונה
  • בקשה | תוכנה לצילום מסך רק כשמשתמשים במחשב

    31
    0 הצבעות
    31 פוסטים
    2k צפיות
    א
    @הגאון-מכולם למה למחוק? @ארץ-הצבי כתב בבקשה | תוכנה לצילום מסך רק כשמשתמשים במחשב: עצירה של תוכנה ע"י סיום המשימה בשורת המשימות
  • שיתוף | בלעדי לפורום קיובייס 13 מתורגם לעברית

    36
    17 הצבעות
    36 פוסטים
    4k צפיות
    O
    @מנצפכ יש תרגום לקיובייס 14?
  • באג | באג כזה �����

    נפתר
    20
    1
    0 הצבעות
    20 פוסטים
    1k צפיות
    יום חדש מתחילי
    @יצחק-קוזניץ בתמונה שהבאת כאן: https://mitmachim.top/post/895681 תסמן וי בשתי הריבועים למטה, ותאשר