ערכות נושא מותאמות אישית – מדריך מקיף
- summary:
מדריך זה מכסה את כל היבטי מערכת ערכות הנושא המותאמות אישית (Custom Themes) – מייבוא VS Code themes ועד יצירה ידנית, הגדרות מתקדמות והדגשת תחביר.
מבוא וסקירה כללית
מהי ערכת נושא מותאמת אישית?
ערכת נושא מותאמת אישית (Custom Theme) היא אוסף של משתני CSS המגדירים את המראה הוויזואלי של הממשק – צבעי רקע, טקסט, כפתורים, קוד ועוד.
היתרונות העיקריים:
התאמה אישית מלאה של המראה לפי טעמכם
ייבוא ערכות מ-VS Code בלחיצה אחת
שמירת מספר ערכות ומעבר ביניהן
תמיכה בהדגשת תחביר (Syntax Highlighting) ייחודית
ההבדל בין Presets לבין Custom Themes
Presets (ערכות מוכנות) |
Custom Themes (ערכות מותאמות) |
|
|---|---|---|
מקור |
מוגדרות מראש במערכת (Dark, Ocean, Classic…) |
נוצרות על ידי המשתמש או מיובאות |
עריכה |
לא ניתנות לעריכה |
ניתנות לעריכה מלאה |
הדגשת תחביר |
קבועה לפי הערכה |
מיובאת מ-VS Code או ברירת מחדל |
שמירה |
במערכת |
ב-MongoDB לפי משתמש |
יכולות המערכת
ייבוא מ-VS Code – תמיכה מלאה בפורמט JSON/JSONC של VS Code themes
יצירה ידנית – עורך צבעים מתקדם עם תצוגה מקדימה חיה
ערכות מוכנות – גלריה של ערכות פופולריות (GitHub, Dracula, Nord…)
הדגשת תחביר – מיפוי אוטומטי של
tokenColorsל-CodeMirror
ייבוא ערכות VS Code
פורמטים נתמכים
המערכת תומכת בשני פורמטי JSON:
JSON רגיל:
קובץ JSON סטנדרטי ללא הערות.
JSONC (JSON with Comments):
פורמט מורחב שתומך בהערות – נפוץ מאוד בערכות VS Code כמו Nord, One Dark Pro ועוד:
{
"name": "My Theme",
/* זו הערה מרובת שורות */
"type": "dark",
"colors": {
// זו הערה של שורה בודדת
"editor.background": "#1a1b26",
"editor.foreground": "#c0caf5",
"focusBorder": "#7aa2f7"
}
}
סוגי הערות נתמכים:
/* ... */– הערות מרובות שורות (multi-line)// ...– הערות של שורה בודדת (single-line)
הערה
המערכת מסירה אוטומטית את ההערות לפני פרסור ה-JSON, כך שאין צורך לערוך את הקובץ ידנית.
מבנה ערכת VS Code
ערכת VS Code מורכבת משלושה חלקים עיקריים:
{
"name": "Theme Name",
"type": "dark",
"colors": {
"editor.background": "#1e1e1e",
"editor.foreground": "#d4d4d4",
"button.background": "#569cd6",
"sideBar.background": "#252526"
},
"tokenColors": [
{
"scope": "comment",
"settings": {
"foreground": "#6a9955",
"fontStyle": "italic"
}
},
{
"scope": ["keyword", "storage"],
"settings": {
"foreground": "#569cd6"
}
}
]
}
הסבר השדות:
name– שם הערכהtype– סוג הערכה:"dark"או"light"(משפיע על ערכי fallback)colors– מילון של צבעי UI (רקעים, טקסט, כפתורים)tokenColors– כללי הדגשת תחביר
מיפוי צבעי UI
המערכת ממפה אוטומטית את צבעי VS Code למשתני CSS שלנו:
VS Code Key |
CSS Variable(s) |
תיאור |
|---|---|---|
|
|
רקע ראשי |
|
|
טקסט ראשי |
|
|
רקע משני |
|
|
רקע שלישוני |
|
|
כפתור ראשי |
|
|
טקסט כפתור |
|
|
כפתור בריחוף |
|
|
רקע שדה קלט |
|
|
גבול שדה קלט |
|
|
גבולות כלליים |
|
|
צבע ראשי |
|
|
צבע קישורים |
|
|
רקע קוד |
|
|
טקסט קוד |
|
|
רקע ניווט |
|
|
רקע כרטיסים |
|
|
צבע שגיאה |
|
|
צבע אזהרה |
|
|
צבע הצלחה |
יצירה ידנית (Native Format)
מבנה הפורמט המקומי
אם אתם מעדיפים ליצור ערכה מאפס, השתמשו בפורמט המקומי:
{
"name": "My Custom Theme",
"description": "ערכה מותאמת אישית",
"variables": {
"--bg-primary": "#1a1b26",
"--bg-secondary": "#24283b",
"--bg-tertiary": "#414868",
"--text-primary": "#c0caf5",
"--text-secondary": "#9aa5ce",
"--text-muted": "#565f89",
"--primary": "#7aa2f7",
"--primary-hover": "#89b4fa",
"--btn-primary-bg": "#7aa2f7",
"--btn-primary-color": "#1a1b26",
"--glass-blur": "12px"
}
}
משתנים חובה
הערכה חייבת לכלול לפחות את המשתנים הבאים לתפקוד תקין:
רקעים וטקסט (Level 2):
--bg-primary רקע ראשי של הדף
--bg-secondary רקע משני (סיידבר, כרטיסים)
--bg-tertiary רקע שלישוני (אלמנטים משניים)
--text-primary טקסט ראשי
--text-secondary טקסט משני
--text-muted טקסט מעומעם
צבעי מותג (Level 1):
--primary צבע ראשי (כפתורים, קישורים, focus)
--primary-hover צבע ראשי בריחוף
--primary-light גרסה בהירה של הצבע הראשי
כפתורים (Level 2):
--btn-primary-bg רקע כפתור ראשי
--btn-primary-color טקסט כפתור ראשי
--btn-primary-border גבול כפתור ראשי
נוספים:
--border-color צבע גבולות
--card-bg רקע כרטיסים
--input-bg רקע שדות קלט
--code-bg רקע קוד
--glass-blur טשטוש glass (בפיקסלים, למשל "12px")
רשימת משתנים מלאה (Whitelist)
חשוב
רק משתנים שנמצאים ברשימה זו יישמרו בעת פרסום ערכה לציבורית.
משתנים שאינם ברשימה יסוננו אוטומטית מטעמי אבטחה.
הרשימה מוגדרת ב-services/theme_parser_service.py (ALLOWED_VARIABLES_WHITELIST).
# Level 1 - Primitives
--primary, --primary-hover, --primary-light
--secondary
--success, --warning, --error
--danger-bg, --danger-border, --text-on-warning
--glass, --glass-blur, --glass-border, --glass-hover
# Level 2 - Semantic Tokens
--bg-primary, --bg-secondary, --bg-tertiary
--text-primary, --text-secondary, --text-muted
--border-color, --shadow-color
--card-bg, --card-border
--navbar-bg
--input-bg, --input-border
--link-color
--code-bg, --code-text, --code-border
--btn-primary-bg, --btn-primary-color, --btn-primary-border
--btn-primary-shadow, --btn-primary-hover-bg, --btn-primary-hover-color
--md-surface, --md-text
--split-preview-bg, --split-preview-meta, --split-preview-placeholder
# Level 2 - Markdown Enhanced (inline code, tables, mermaid)
--md-inline-code-bg, --md-inline-code-border, --md-inline-code-color
--md-table-bg, --md-table-border, --md-table-header-bg
--md-mermaid-bg
# Level 3 - Collections
--collections-link-override
# Level 3 - Global Search
--search-suggestion-text-override
דריסת טוקן שאין לו מקבילה ב-VS Code
חלק מהטוקנים אינם נגזרים משום מפתח של VS Code, כי אין להם מקבילה שם. --collections-link-override הוא כזה: הוא צובע את שמות הקבצים בדף /collections — גם בכרטיס אוסף וגם בשולחן העבודה, שני מסכים נפרדים שמרנדרים את אותו סוג קישור. בכוונה אין לו ערך ברירת מחדל בשום מקום, ולכן ה-CSS נופל לערך שנצבע היום כשהערכה אינה מצהירה עליו.
בערכה מיובאת שאינה מצהירה עליו, שמות הקבצים מקבלים את --primary של הערכה. זה נכון לרוב הערכות, אבל כרטיס האוסף נשאר לבן גם בערכות כהות — ולכן ערכה שה---primary שלה בהיר מקבלת טקסט בהיר על רקע בהיר.
כדי לפתור את זה בערכה בודדת, בלי להשפיע על שאר הערכות, אפשר להוסיף בלוק variables לצד colors באותו קובץ VS Code:
{
"name": "Cobalt Next",
"type": "dark",
"colors": {
"editor.background": "#1b2b34",
"editor.foreground": "#d8dee9",
"focusBorder": "#ffffff"
},
"tokenColors": [],
"variables": {
"--collections-link-override": "#2e6161"
}
}
הבלוק עובר את אותה ולידציה ואת אותה רשימה לבנה כמו כל שאר הטוקנים — ערך שאינו צבע תקין מוחזר עם 400 ומציין את המפתח, ולא נזרק בשקט — ומתמזג מעל התוצאה שנגזרה מ-colors. tokenColors ממשיך להיות מעובד כרגיל, ולכן הדגשת התחביר אינה נפגעת. שימו לב ש-colors חייב להכיל לפחות שלושה מפתחות, אחרת הייבוא נדחה.
הערה
ערכה שאינה מצהירה על הטוקן מרונדרת ללא כל שינוי, בשני המצבים: webapp/static/css/collections.css נופל ל-var(--primary) במצב רגיל ול-var(--primary-dark) ב-:hover — בדיוק הערכים שנצבעו גם קודם. זו דריסה בהצטרפות מרצון, לא שינוי גורף.
הצעות ההשלמה בחיפוש הגלובלי
--search-suggestion-text-override הוא וו מאותו סוג בדיוק, ובאותו מסלול שורש. ההצעות שקופצות מתחת לתיבת החיפוש הגלובלי מרונדרות ב-webapp/static/js/global_search.js כאלמנטי <a>, ולכן [data-theme="custom"] a שב-dark-mode.css צובע אותן ב-var(--primary) — ספציפיות שגוברת על כלל המחלקה שב-global_search.css. רקע התיבה, לעומת זאת, אינו של הערכה כלל: הוא --solid-surface-bg, שנשאר לבן בכל ערכה. כלומר צבע הטקסט נגזר מהערכה והרקע לא, והניגודיות יוצאת מקרית — ערכה שה---primary שלה לבן מקבלת טקסט לבן על רקע לבן.
ההצהרה נראית זהה, ושני הטוקנים יכולים לחיות באותו בלוק:
"variables": {
"--collections-link-override": "#2e6161",
"--search-suggestion-text-override": "#2e6161"
}
הערה
כאן יש שלושה מצבים ולא שניים, ולכל אחד var() משלו ב-webapp/static/css/global_search.css: המצב הרגיל נופל ל-var(--primary), :hover נופל ל-var(--primary-dark), ו-:focus-visible נופל ל-var(--suggestions-text). השלישי אינו טעות: .search-suggestion:focus-visible מנצח כבר היום את כלל ה-<a> בזכות ספציפיות, ולכן הערך שנצבע בו היום שונה משני האחרים. ערכה שאינה מצהירה מרונדרת זהה לחלוטין בשלושת המצבים.
אזהרה
הערך נשמר ב-MongoDB בזמן הייבוא. ערכה שכבר קיימת בחשבון אינה מכירה טוקן שנוסף אחריה — צריך לייבא אותה מחדש. זו הסיבה הראשונה לבדוק כשההצהרה נוספה ולא נראה שינוי.
הדגשת תחביר (Syntax Highlighting)
כאשר מייבאים ערכת VS Code עם tokenColors, המערכת ממירה אותם אוטומטית להדגשת תחביר עבור CodeMirror ו-Pygments.
ארכיטקטורה
זרימת המרת צבעים מ-VS Code ל-CodeMirror:
tokenColors (VS Code)
│
▼
VSCODE_TO_CM_TAG מיפוי
│
▼
syntax_colors JSON
│
▼
HighlightStyle.define() (CodeMirror)
מנגנון Fallback
כאשר ערכה לא מגדירה צבע לתג ספציפי, המערכת יורשת מתגים הוריים:
function(definition(variableName))
│
├── יורש מ-definition(variableName)
│ │
│ └── יורש מ-variableName
│ │
│ └── יורש מ-name
│
└── יורש מ-function(variableName)
│
└── יורש מ-variableName
דוגמה:
אם הערכה מגדירה צבע רק ל-variableName, כל ההגדרות שיורשות ממנו יקבלו את אותו הצבע עד שתוגדר דריסה ספציפית.
CodeMirror CSS Classes
מעבר ל-Tags המשמשים ב-HighlightStyle.define(), המערכת תומכת גם ב-CSS Classes עבור classHighlighter. אלו מאפשרים דריסה ישירה ב-CSS:
Classes בסיסיים:
CSS Class |
תיאור |
|---|---|
|
הערות |
|
מחרוזות (רגילות / template) |
|
מילות מפתח |
|
מספרים |
|
אופרטורים |
|
סימני פיסוק |
|
קבועים וערכי boolean |
|
ערכים ליטרליים |
משתנים ופונקציות:
CSS Class |
תיאור |
|---|---|
|
משתנים רגילים |
|
הגדרות משתנים (צבע שונה) |
|
משתנים מקומיים (לעתים עם italic) |
|
משתנים מיוחדים (self, this, super) |
|
פונקציות |
|
מאקרו / decorators |
טיפוסים ומחלקות:
CSS Class |
תיאור |
|---|---|
|
שמות מחלקות |
|
שמות טיפוסים |
|
namespaces / modules |
|
שמות properties |
|
הגדרות properties |
HTML/XML:
CSS Class |
תיאור |
|---|---|
|
תגיות HTML/XML |
|
מאפיינים |
|
סוגריים זוויתיים |
עיצוב טקסט (Markdown):
CSS Class |
תיאור |
|---|---|
|
כותרות |
|
טקסט נטוי (italic) |
|
טקסט מודגש (bold) |
|
קישורים |
|
ציטוטים |
|
קוד inline |
מיוחדים:
CSS Class |
תיאור |
|---|---|
|
מטא-דאטה |
|
labels |
|
שורות שנוספו (git diff) |
|
שורות שנמחקו (git diff) |
|
שורות ששונו |
|
קוד לא תקין |
דוגמת CSS לדריסה:
/* דריסת צבע הגדרות פונקציות */
:root[data-theme="custom"] .tok-variableName.tok-definition {
color: #7aa2f7 !important;
font-weight: bold !important;
}
/* משתנים מקומיים באיטליק */
:root[data-theme="custom"] .tok-variableName.tok-local {
color: #bb9af7 !important;
font-style: italic !important;
}
/* self/this בצבע מיוחד */
:root[data-theme="custom"] .tok-variableName2 {
color: #f7768e !important;
}
/* שורות שנוספו בדיף */
:root[data-theme="custom"] .tok-inserted {
color: #9ece6a !important;
background: rgba(158, 206, 106, 0.1);
}
/* שורות שנמחקו בדיף */
:root[data-theme="custom"] .tok-deleted {
color: #f7768e !important;
background: rgba(247, 118, 142, 0.1);
}
הערה
ה-!important נדרש כדי לדרוס את ה-inline styles שמוזרקים על ידי CodeMirror themes.
הסלקטור :root[data-theme="custom"] מבטיח שהדריסות יחולו רק כשערכה מותאמת פעילה.
אבטחה וולידציה
ולידציית צבעים
המערכת מאפשרת רק פורמטים בטוחים:
פורמטים נתמכים:
#fff Hex קצר (3 תווים)
#ffff Hex עם alpha (4 תווים)
#ffffff Hex מלא (6 תווים)
#ffffffff Hex עם alpha (8 תווים)
rgb(r, g, b) RGB (ערכים 0-255)
rgba(r, g, b, a) RGBA עם שקיפות (alpha 0-1)
ערכים חסומים (אבטחה):
url(...) CSS injection
expression(...) IE legacy injection
javascript: XSS
data: Data URI injection
@import CSS import injection
סניטציה
המערכת מבצעת מספר שלבי ניקוי:
הסרת הערות JSONC – לפני פרסור ה-JSON
בדיקת תקינות JSON – וולידציה של מבנה הקובץ
ולידציית צבעים – לפי ה-Regex המגביל
בדיקת whitelist – רק משתנים מוכרים מותרים
הגבלת גודל – מניעת קבצים גדולים מדי
אזהרה
לא כל ערך פסול מטופל באותה דרך, וההבדל חשוב:
ערך פסול בבלוק
variables— הייבוא נדחה עם400, וההודעה מציינת את המפתח.מפתח שאינו ברשימה הלבנה — עובר את הוולידציה ואז מסונן בשקט, עם אזהרה בלוג.
ערך פסול בתוך
colors— עובר את הוולידציה, והטוקן שהוא ממופה אליו נופל לערך ברירת המחדל, עם אזהרה בלוג.
כלומר שתי הצורות האחרונות אינן מפילות את הייבוא. אם ערכה נשמרה אך צבע מסוים אינו מופיע, זו הסיבה הסבירה.
API Reference
Endpoints
רשימת ערכות:
GET /api/themes
מחזיר רשימת כל הערכות של המשתמש (ללא variables הכבדים).
פרטי ערכה:
GET /api/themes/<id>
מחזיר ערכה מלאה כולל variables לעריכה.
יצירת ערכה:
POST /api/themes
Content-Type: application/json
{
"name": "My Theme",
"variables": {...}
}
ייבוא ערכה:
POST /api/themes/import
Content-Type: application/json
{
"json_content": "{...JSON content...}"
}
הפורמט מזוהה מתוך התוכן עצמו ולא נמסר כפרמטר: קובץ שיש בו מפתח colors מפורסר כערכת VS Code, וכל השאר כפורמט המקומי. לחלופין אפשר להעלות ב-multipart/form-data תחת השדה file, בסיומת .json.
עדכון ערכה:
PUT /api/themes/<id>
Content-Type: application/json
{
"name": "Updated Name",
"variables": {...}
}
הפעלת ערכה:
POST /api/themes/<id>/activate
מפעיל את הערכה (מכבה את כל האחרות) ומעדכן ui_prefs.theme="custom".
ביטול הפעלה:
POST /api/themes/deactivate
מבטל את כל הערכות המותאמות וחוזר ל-Classic.
מחיקת ערכה:
DELETE /api/themes/<id>
מוחק ערכה. אם הייתה פעילה – חוזרים ל-Classic.
מבנה תגובה
{
"success": true,
"theme": {
"id": "uuid-string",
"name": "My Theme",
"description": "תיאור הערכה",
"is_active": true,
"source": "vscode",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"variables": {
"--bg-primary": "#1a1b26"
// ... additional variables
},
"syntax_css": "/* CodeMirror CSS */",
"syntax_colors": {
"keyword": {"color": "#7aa2f7"}
// ... additional colors
}
}
}
פתרון בעיות (Troubleshooting)
בעיות נפוצות
”קובץ JSON לא תקין“:
בדקו שאין הערות שגויות (
//בתוך מחרוזת)ודאו שכל הסוגריים מאוזנים
בדקו שאין פסיקים מיותרים בסוף
צבעים לא מופיעים:
ודאו שפורמט הצבע תקין (
#fff,#ffffff,rgb(...))בדקו שהמשתנה נמצא ברשימת ה-whitelist
בדקו את לוג האזהרות בקונסול
הדגשת תחביר לא עובדת:
ודאו שהערכה מיובאת מ-VS Code ומכילה
tokenColorsערכות שנוצרו ידנית לא כוללות הדגשת תחביר ייחודית
בדקו שה-
syntax_colorsנשמר כראוי
הערכה לא נשמרת:
ודאו שאתם מחוברים למערכת
בדקו שלא עברתם את מגבלת 10 הערכות
בדקו הרשאות כתיבה למסד הנתונים
דוגמה לייבוא ערכת Nord
הורידו את קובץ
nord-theme.jsonמהריפו הרשמיפתחו את Theme Builder בהגדרות
לחצו ”ייבוא מ-VS Code“
העלו את הקובץ
שמרו והפעילו
קישורים קשורים
ראה גם
מערכת ערכות הנושא והטוקנים החדשה – תיעוד ארכיטקטורת הטוקנים והערכות
GUIDES/custom_themes_guide.md– מדריך פנימי מורחבservices/theme_parser_service.py– קוד המקור של הפרסורservices/theme_presets_service.py– ניהול ערכות מוכנותwebapp/static/data/theme_presets.json– קובץ ה-Presets