المحررات وسطر الأوامر وسلاسل أدوات الأتمتة
الخلاصة: تحل المحررات مشكلة "أن تراه بوضوح وتحرره بشكل صحيح"، بينما يحل سطر الأوامر مشكلة "الدفعات والتكرار". لدى كل جانب أدوات قليلة تظل مفيدة لعقد من الزمن.

الخلاصة: اختر المحرر بحسب السياق — CodeMirror 6 لمواقع الأدوات والجوال، وMonaco فقط عندما تحتاج تجربة IDE كاملة؛ وكل الأعمال الدفعية إلى jq مع ثلاثة فحوص CI للصياغة والبنية والنمط، ومرّر الوسائط دائمًا عبر jq --arg.
يجب أن يكون عصر فحص JSON يدويًا قد انتهى: أي شيء تستطيع الآلة تكراره، لا تتركه للعيون البشرية.
1. المحررات في المتصفح
1.1 دمج CodeMirror 6 بأقل قدر
import { EditorView, basicSetup } from 'codemirror';
import { json, jsonParseLinter } from '@codemirror/lang-json';
import { linter, lintGutter } from '@codemirror/lint';
const view = new EditorView({
parent: document.getElementById('editor')!,
doc: '{"hello": "json"}',
extensions: [
basicSetup,
json(),
linter(jsonParseLinter()),
lintGutter(),
EditorView.updateListener.of((update) => {
if (update.docChanged) {
// استخدم debounce قبل العمل الثقيل؛ لا تنسّق عند كل ضغطة مفتاح
scheduleParse(update.state.doc.toString());
}
}),
],
});
أربع نقاط جديرة بالملاحظة:
json()يوفر تلوين الصياغة ومطابقة الأقواس — لا تكتبها بنفسك؛jsonParseLinter()ينتج علامات خطأ على مستوى السطر والعمود؛ اقرنه بـlintGutter()لإظهار أيقونات بجوار أرقام الأسطر؛- يجب أن يمر
updateListenerعبر debounce؛ فاستدعاءJSON.parseعلى مئة ألف سطر عند كل ضغطة مفتاح سيُحدث تأخرًا ملحوظًا؛ - المستندات الكبيرة تحتاج تحسينات تتجاوز
EditorView.lineWrappingلتجنب عرض كل شيء دفعة واحدة (CodeMirror 6 يعرض بحسب منطقة العرض افتراضيًا، وهو تحسن على الإصدارات الأقدم).
1.2 الطي والمخططات
يمتلك CodeMirror 6 طيًا مدمجًا؛ وفي سياقات JSON تطوي عادة وفق "الكائن/المصفوفة":
import { foldGutter, foldKeymap } from '@codemirror/language';
import { keymap } from '@codemirror/view';
مع foldGutter() وkeymap.of(foldKeymap)، يستطيع المستخدمون طي المصفوفات الطويلة باختصار لوحة المفاتيح.
1.3 الاختيار بين CodeMirror وMonaco
| البعد | CodeMirror 6 | Monaco |
|---|---|---|
| حجم الحزمة | صغير، معياري | كبير (عدة ميغابايت) |
| الجوال | مدعوم جيدًا | تجربة متوسطة |
| خدمات اللغة | عليك بناؤها بنفسك | غنية ومدمجة |
| كلفة التخصيص | منخفضة | متوسطة |
مواقع الأدوات والجوال أولًا → CodeMirror؛ تجربة IDE كاملة (ملفات متعددة، الانتقال إلى التعريف، الإكمال) → Monaco.
2. سطر الأوامر: ست وصفات jq عالية التكرار
jq بالنسبة إلى JSON هو ما sed + awk بالنسبة إلى النص؛ وتعلم جزء صغير من صياغته يغطي ثمانين بالمئة من الاحتياجات اليومية.
# 1. اختيار الحقول (الأكثر شيوعًا)
jq '.data.items[].name' response.json
# 2. التصفية وإعادة التشكيل
jq '.data.items[] | select(.price < 10) | {id, price}' response.json
# 3. التجميعات (length وsum وmax)
jq '[.items[] | .price] | {count: length, total: add, max: max}' response.json
# 4. التجميع والتحصيل
jq '[.items[]] | group_by(.category) | map({category: .[0].category, count: length})' response.json
# 5. دمج ملفات متعددة في مصفوفة
jq -s '.' part-*.json > merged.json
# 6. معالجة JSON Lines سطرًا بسطر
jq -c 'select(.level == "error")' app.jsonl
# مفاتيح الخرج الشائعة
jq -r '.data.name' # إزالة علامات الاقتباس ليُمرر بسلاسة إلى الصدفة
jq -c '.' # خرج مضغوط في سطر واحد
jq --arg id "$ID" '.id == $id' # تمرير الوسائط بأمان، وتجنب الحقن عبر الدمج
يستحق --arg ذكرًا خاصًا: دمج متغير مباشرة في تعبير ينكسر بمجرد أن تحتوي القيمة على علامات اقتباس، بينما يتولى --arg عملية الهروب في jq.
2.1 أدوات أخرى في لمحة
| الأداة | الغرض | في جملة واحدة |
|---|---|---|
yq |
التحويل بين YAML/JSON/XML | صياغة شبيهة بـ jq، وهي العاملة الأساسية لملفات الإعداد |
dasel |
استعلام موحّد عبر الصيغ | يدعم JSON/YAML/TOML/XML/CSV |
fx |
تصفح تفاعلي لـ JSON | تنقّل في الطرفية، جيد للاستكشاف |
jless |
تصفح مُصفّح الصفحات في الطرفية | مثل less، مع الطي والبحث |
gron |
تسطيح JSON إلى أسطر قابلة لـ grep | أداة رائعة لمعرفة "في أي طبقة يقع هذا الحقل" |
ajv-cli |
التحقق من المخطط | تحقق من ملفات JSON في CI |
فكرة gron جديرة بالمعرفة خاصة:
$ echo '{"a":{"b":[1,2]}}' | gron
json = {};
json.a = {};
json.a.b = [];
json.a.b[0] = 1;
json.a.b[1] = 2;
بعد التسطيح، يستطيع grep تحديد المسار، وهو أسرع بكثير من التوسيع طبقة بطبقة في محرر.
3. ثلاث طبقات للتحقق في CI
| الطبقة | الأداة | ماذا يعني الفشل |
|---|---|---|
| الصياغة | JSON.parse / jq empty |
الملف نفسه مشوّه |
| البنية | ajv-cli + مخطط |
حقول مفقودة، أنواع خاطئة |
| النمط | Prettier | تنسيق غير متسق، فروق مثيرة للضجيج |
# الصياغة: تحقق دفعي من كل ملف json في المستودع
find . -name '*.json' -not -path './node_modules/*' -print0 \
| xargs -0 -n1 jq empty
# البنية: التحقق مقابل مخطط
npx ajv-cli validate -s schemas/order.json -d 'fixtures/orders/*.json' --strict=false
# النمط: فحص فقط، دون تعديل
npx prettier --check "**/*.json"
تحتاج إلى الطبقات الثلاث جميعها، لأن رسائل خطئها مختلفة تمامًا:
يقول jq empty فقط "أي سطر مكسور"، ويقول ajv "أي حقل ينتهك أي كلمة مفتاحية"، ويقول Prettier فقط "التنسيق غير متسق".
4. خطافات pre-commit
# مثال .husky/pre-commit (مقتطف)
npx lint-staged
{
"lint-staged": {
"*.json": ["prettier --write", "jq empty"]
}
}
كن حذرًا مع ملفات إعداد الأدوات مثل package.json وtsconfig.json؛ لا تدع Prettier يعيد إزاحتها بلا مبالاة —
بعض الأدوات حساسة للتنسيق (JSON الصالح يجب ألا يكون كذلك، لكن عمليًا تسبب هذا في مشكلات). يمكنك استثناءها فرادى.
5. نصائح التصحيح
- استخدم
jq -eكتحقق: رمز الخروج 1 عندما تكون نتيجة التعبيرfalseأوnull، فيمكن إدخاله مباشرة في السكربتات كفحص؛ - يسرد
jq 'paths'كل المسارات، ما يمنحك نظرة سريعة على بنية مستند غير مألوف؛ jq '.. | objects | keys'يعثر على كل اسم مفتاح ظهر يومًا، وهو مفيد لاصطياد الصياغة غير المتسقة؛- نسّق قبل المقارنة في المحرر: diff غير المنسّق ضجيج محض؛ والمقارنة البنيوية مثل
/diffأدق.
6. قائمة الفحص
- [ ] علامات الخطأ في المحرر دقيقة إلى السطر والعمود، والتحليل يمر عبر debounce؛
- [ ] سكربتات الفريق تمرّر الوسائط بـ
jq --argبدلًا من دمج النصوص؛ - [ ] لدى CI طبقات التحقق الثلاث (الصياغة/البنية/النمط)؛
- [ ] يعالج pre-commit الملفات المهيأة فقط، فلا يُبطئ المسح الكامل عمليات الإيداع؛
- [ ] إصدارات الأدوات مثبتة في
package.jsonأو.tool-versions.
الأسئلة الشائعة
كيف أختار بين CodeMirror 6 وMonaco؟
لمواقع الأدوات والجوال، فضّل CodeMirror 6: صغير ومعياري ومدعوم جيدًا على الجوال، ويمكن تركيب تلوين الصياغة ومطابقة الأقواس والطي حسب الحاجة. لا تلجأ إلى Monaco إلا عندما تحتاج تجربة IDE كاملة بملفات متعددة والانتقال إلى التعريف والإكمال — بكلفة حزمة بعدة ميغابايت وجهد تخصيص أعلى.
لماذا يحتاج CI إلى فحوص الصياغة والبنية والنمط معًا؟
تُبلّغ الطبقات الثلاث عن أخطاء مختلفة تمامًا: يقول jq empty أي سطر مكسور، ويقول ajv أي حقل ينتهك أي كلمة مفتاحية، ويقول Prettier فقط إن التنسيق غير متسق. إسقاط طبقة يجعل أخطاء غيرها عرضة لسوء الفهم، فأبقِ الثلاث وتوقف فور فشل أي طبقة.
هل أعتمد على pre-commit بدلًا من التحقق في CI؟
لا. تعالج الخطافات الملفات المهيأة فقط، ما يمنح ملاحظات في أقل من دقيقة لكنه لا يغطي المستودع كاملًا ولا التغييرات التي تتجاوز الإيداع. CI مسؤول عن الاكتمال: أبقِ pre-commit على الملفات المهيأة واترك المسوح الكاملة لـ CI.