:summary: העמוד הציבורי של עורך ה-Markdown: מאיפה מגיעים הערכה וטקסט ההדגמה, איך הוא משתמש בעורך, בתצוגה החיה ובסרגל ה-MD של עמוד העריכה, איך נשמרת הטיוטה בדפדפן, איך מייצאים ממנו HTML מעוצב בלי לשלוח את הטקסט לשרת, ואיך מנועי חיפוש מוצאים אותו. .. _webapp-markdown-editor: העורך הציבורי (``/markdown-editor``) ===================================== עמוד ציבורי, בלי התחברות, לגולשים שמחפשים עורך Markdown: העורך מימין, התצוגה החיה משמאל, ושורה של כלי Markdown מעליהם. בכניסה הראשונה העורך מציג טקסט הדגמה, והטקסט שכותבים נשמר בדפדפן ומחכה בביקור הבא. הראוט הוא ``markdown_editor`` ב-``webapp/app.py``, הנתונים שהעמוד נשען עליהם ב-``webapp/markdown_editor.py``, התבנית ``webapp/templates/markdown_editor.html``, והסקריפט של העמוד ``webapp/static/js/markdown-editor.js``. העמוד לא דורש התחברות ופטור ממגבלת הקצב הגורפת, כמו ``/gallery`` (:ref:`webapp-gallery`). הערכה ------ - **ערכה אחת לכל גולש.** העמוד מוצג בערכה הציבורית ש-``THEME_ID`` ב-``webapp/markdown_editor.py`` מצביע עליה, גם למשתמש מחובר שבחר ערכה אחרת לשאר האתר. הראוט טוען אותה כמו ערכה ציבורית של מבקר (``_load_shared_theme_for_request`` בלי משתמש, דרך הקאש), ומעביר אותה ל-``render_template`` במפורש: ערך שמועבר שם גובר על מה ש-``inject_globals`` מחזיר. - **ערכה מותאמת של המשתמש מאופסת** (``custom_theme``), כי צבעי התחביר שלה כתובים על ``[data-theme-type="custom"]``, שחל גם על ערכה ציבורית. - **כשהערכה חסרה** — נמחקה, כובתה, או שהמסד לא זמין — העמוד עולה בערכה הרגילה של האתר, ונרשמת אזהרה בלוג. - **מגבלה ידועה:** הסנכרון בין טאבים ב-``base.html`` מחיל ערכה שהוחלפה בטאב אחר גם על העמוד הזה, עד שהוא נטען מחדש. טקסט ההדגמה ------------- - **הקובץ** הוא ``webapp/markdown_editor_demo.md``, עותק של המסמך ``CodeKeeper_Markdown.md`` ב-CodeKeeper, בלי הכותרות H5 ו-H6, שהתצוגה החיה לא מרנדרת (ראו "התצוגה החיה בלי ``¶`` ובלי H5/H6" למטה). העמוד מציג את העותק שבריפו: שינוי במסמך ב-CodeKeeper לא מגיע לעמוד בלי עדכון של הקובץ. - **הקריאה** ב-``demo_text()``, בבקשה הראשונה ולא בזמן ייבוא, ונשמרת בזיכרון של התהליך. ``lru_cache`` שומר רק ערך שהוחזר, ולכן קובץ שחסר בבקשה אחת יימצא בבאה. - **הוא עובר לתבנית כמשתנה, ו-Jinja מברח אותו לתוך ה-textarea.** לא ``{% include %}``: בטקסט יש ``{{ __html: html }}``, ו-include היה מריץ אותו כתבנית. - **"טען דוגמה"** קורא אותו בחזרה מ-``textarea.defaultValue`` — התוכן שהשרת שלח בתוך התגית, שכתיבה בעורך אינה משנה. העורך, התצוגה החיה וסרגל ה-MD -------------------------------- העמוד משתמש באותם רכיבים כמו עמוד העריכה, ולכן תיקון באחד מהם מגיע לשניהם. מה שהעמוד צריך אחרת עובר כאפשרות שרק הוא מפעיל, ועמודי העריכה וההעלאה לא מושפעים ממנה: - **העורך** (``EditorManager`` ב-``editor-manager.js``): ``initEditor`` עם ``fixedEditor: true``. העורך תמיד CodeMirror, בלי כפתור המעבר לעורך הפשוט, ובלי להתחשב בהעדפת העורך או לשמור אותה — ההעדפה שייכת לעמודי העריכה, ושמירתה נשלחת ל-API של משתמש מחובר. "בחר הכל", "העתק" ו"הדבק" נשארים, ולפניהם "בטל" ו"בצע שוב" — אייקון בלי טקסט, על ההיסטוריה של העורך, כמו בעמודי העריכה וההעלאה. בסוף השורה אין תווית, וההודעה הזמנית צפה שם (:doc:`/webapp/editor`). אם CodeMirror נכשל, העורך הפשוט עולה, כדי שאפשר יהיה להמשיך לכתוב. - **מימין לשמאל, חוץ מבלוקי קוד** — ``initEditor`` עם ``textDirection: 'rtl'``. העורך כולו מימין לשמאל, ורק השורות של בלוק קוד (בין גדרות של שלושה גרשיים הפוכים, כולל שורות הגדר, או מוזח) משמאל לימין, לפי מה שהמנתח של Markdown בעורך זיהה. עד אוקטובר 2026 כל שורה קיבלה את הכיוון של האות החזקה הראשונה בה, ולכן ``- [x] משימה``, שורת היישור של טבלה (``|---:|``) וקישור באנגלית בתוכן העניינים יצאו משמאל לימין. המנגנון והחבילה של CodeMirror שהוא יושב בה — :doc:`/webapp/editor`. עמודי העריכה וההעלאה נשארים משמאל לימין, כמו עורך קוד. - **התצוגה החיה** (``LivePreviewController`` ב-``live-preview.js``), לפי מאפיינים על ``#livePreviewRoot``: - ``data-preview-mode="markdown"`` — תמיד Markdown. בלעדיו המצב נקבע לפי השפה ושם הקובץ, ובעמוד בלי השדות האלה התצוגה לא הייתה זמינה. - ``data-preview-autostart`` — דלוקה מההתחלה. הכפתור "Live Preview" נשאר, ומכבה אותה. - ``data-preview-client-only`` — רינדור בדפדפן בלבד. בעמוד העריכה, כשהרינדור בדפדפן נכשל, הבקר פונה ל-``/api/preview/live``; כאן הנתיב הזה דורש התחברות, ולכן העמוד מציג שגיאה במקום לשלוח את הטקסט. - **סרגל ה-MD** (המאקרו ``markdown_toolbar`` ב-``components/editor_components.html``, ו-``markdown-toolbar.js``): ``markdown_toolbar(inline=True, markdown_only=True)``. ``inline`` מציג את הכלים כשורה פתוחה, בלי הכפתור "MD", והשורה נשארת במקומה ואינה עוברת לשורת העורך; ההתראות נפתחות מ"התראות ▾" בלחיצה, ונסגרות בלחיצה שנייה, בלחיצה מחוץ לסרגל או ב-Escape. ``markdown_only`` מציג את הסרגל ומפעיל את קיצורי המקלדת שלו תמיד, בלי לבדוק שם קובץ ושפה. בלי הפרמטרים, המאקרו מוציא את אותן תגיות כמו קודם. בשורה הפתוחה המארקר מסומן 🟰 וההתראות ℹ️, ורשימת ההתראות בעברית — השם של כל סוג הוא הכותרת שההתראה מקבלת במסמך (``ADMONITION_TITLES`` ב-``admonition-icons.js``), וגם ההודעה אחרי ההוספה (``getTemplateLabel``); השמות כתובים גם בתבנית (``alert_items``), ו-``tests/test_markdown_editor_page.py`` משווה. בתפריט "MD" של עמודי העריכה וההעלאה האייקונים והשמות באנגלית נשארו. - **הפריסה — כל הגובה לכתיבה ולתצוגה.** אין כרטיס עוטף: ה-Split View הוא המסגרת. שורת כלי ה-MD יושבת בראש שלו (``.split-toolbar``), ו-"Live Preview" בסופה, משמאל; הקיצור Ctrl+Shift+Enter עבר לטולטיפ של הכפתור. התווית של העורך מוסתרת ויזואלית (``sr-only``) ונשארת לקורא מסך. בטלפון (עד 767px) העורך והתצוגה מוצגים אחד בכל פעם, עם לשוניות "עורך" / "תצוגה חיה" — רק כשהתצוגה דלוקה; כמו בעמודי העריכה וההעלאה (:doc:`/webapp/theming_and_css`, בסעיף על Split View). בעורך אין מספרי שורות ואין חיצי קיפול (``gutters: false``), והטקסט מתחיל במרווח קטן מהקצה — הריווח של השורה לפי הכיוון שלה (``.codemirror-container--rtl .cm-line`` ב-``codemirror-custom.css``). בתצוגה, שורת המידע (שפה, גודל, זמן) מוסתרת, והסטטוס מוצג רק בשגיאה — כמו בעמודי העריכה וההעלאה, מכלל אחד ב-``split-view.css`` (:doc:`/webapp/theming_and_css`, בסעיף על Split View). שאר הכללים של הפריסה בבלוק ה-``