يتضمن كل تصدير من figmascope ملف tokens.json. إنه الجسر بين القيم البصرية في Figma والثوابت المكتوبة التي يحتاجها كودك. يتناول هذا المقال المخطط، وكيفية تسمية المفاتيح، وما يحدث حين لا يحتوي ملف Figma على متغيرات، وأين يقصر نظام الرموز بصدق.

المخطط

البنية العليا لها أربعة أقسام:

{
  "spacing": {
    "spacing.4":  { "$value": 4,  "$type": "dimension" },
    "spacing.8":  { "$value": 8,  "$type": "dimension" },
    "spacing.12": { "$value": 12, "$type": "dimension" },
    "spacing.16": { "$value": 16, "$type": "dimension" },
    "spacing.24": { "$value": 24, "$type": "dimension" }
  },
  "radius": {
    "radius.4":  { "$value": 4,  "$type": "dimension" },
    "radius.8":  { "$value": 8,  "$type": "dimension" },
    "radius.12": { "$value": 12, "$type": "dimension" }
  },
  "color": {
    "color.7f5cfe": { "$value": "#7f5cfe", "$type": "color" },
    "color.ffffff": { "$value": "#ffffff", "$type": "color" },
    "color.1a1a2e": { "$value": "#1a1a2e", "$type": "color" }
  },
  "typography": {}
}

الصيغة شبيهة بـ W3C Design Tokens Community Group: كل رمز كائن بـ $value و$type. إنها ليست تطبيقًا صارمًا لـ W3C DTCG — figmascope سبق نشر المواصفة النهائية ولا تطبّق أنواعًا مركّبة كـ fontFamily — لكنها قريبة بما يكفي أن أدوات DTCG يمكنها تحليلها بتعديل طفيف.

كائن typography الفارغ ليس خطأً. يُغطَّى أدناه.

تسمية المفاتيح المشتقة من القيمة

حين يحتوي ملف Figma على متغيرات، تأتي مفاتيح الرموز من أسماء المتغيرات التي حددها المصمم. spacing.md، color.brand.primary، أيًا كان ما يستخدمه نظام التصميم.

حين لا يحتوي ملف Figma على متغيرات — وهو الحال مع غالبية ملفات Figma في العالم الحقيقي — يتراجع figmascope إلى التسمية المشتقة من القيمة. قيمة مسافة 16 تصبح spacing.16. اللون #7f5cfe يصبح color.7f5cfe. نصف قطر الزوايا 4 يصبح radius.4.

هذا مقايضة مقصودة. الأسماء المشتقة من القيمة قبيحة لكنها مستقرة. مشتقة من القيمة الفعلية، لذا تشغيلان مختلفان للملف Figma ذاته ينتجان المفتاح ذاته. spacing.16 يعني دائمًا 16dp. يمكن للوكيل الاعتماد على ذلك.

البديل سيكون أسماء موضعية كـ spacing.1 وspacing.2 إلخ. تلك هشّة — أضف قيمة مسافة أصغر وكل شيء يتحوّل. الأسماء المشتقة من القيمة لا تتحوّل.

الأسماء المشتقة من القيمة خطة احتياطية للملفات التي ينبغي أن تحتوي على متغيرات لكنها لا تحتوي. إن كان نظام تصميمك يحتوي على 40 قيمة مسافة تحتاج أسماءً دلالية، اطلب من المصمم إعداد متغيرات. الخطة الاحتياطية للاستنتاج موجودة للملفات الحقيقية، لا كبديل عن نظام رموز حقيقي. يمكنك تشغيل figmascope على ملفك الخاص لمعرفة مسار المصدر الذي يسلكه.

حقل tokensSource وما يعنيه

يتضمن _meta.json حقل tokensSource يخبرك كيف اشتُقَّت الرموز:

القيمةالمعنى
"figma-variables" ملف Figma يحتوي على متغيرات واستُخدمت مباشرةً. أسماء الرموز يُعيّنها المصمم. تغطية كاملة.
"inferred-from-frequency" لا متغيرات. فحص figmascope جميع العقد، وعثر على قيم متكررة بكثرة، ورفعها إلى رموز. التغطية تعتمد على اتساق التصميم.
"none" لا متغيرات والاستنتاج لم يُنتج شيئًا مفيدًا. ستحتوي أقسام tokens.json على فراغ أو شبه فراغ.

تحذير "tokens-inferred-from-frequency" في _meta.json يعكس هذا. إن رأيته، فالتغطية الرمزية بأفضل جهد ممكن.

حين يكون tokensSource هو "inferred-from-frequency"، خوارزمية الاستنتاج هي: إيجاد جميع قيم الأبعاد التي تظهر في ثلاثة عقد أو أكثر في حقول الحشو والفجوة أو cornerRadius. رفع تلك إلى رموز مسافات أو نصف قطر على التوالي. فعل الشيء ذاته لألوان التعبئة. القيم التي تظهر مرة أو مرتين فقط تُعامَل كحالة خاصة لا تُرفع.

يعمل هذا جيدًا للتصاميم المتسقة داخليًا. يعمل بشكل سيئ للتصاميم الاستكشافية حيث تتباين المسافات بحرية. تحذيرات _meta.json موجودة تحديدًا لكي يعرف الوكيل أيّ الحالتين يواجه.

لماذا الطباعة فارغة في أغلب الأحيان

رموز الطباعة تتطلب متغيرات Figma من نوع FLOAT أو STRING لاستخراجها بشكل موثوق. أنماط النصوص موجودة في Figma كأنماط مشتركة لا متغيرات، وسطح واجهة برمجة التطبيقات للأنماط يختلف عن واجهة المتغيرات.

يستخرج figmascope v0.4 الطباعة حين تغطيها المتغيرات. لا يُحاول الاستنتاج القائم على التكرار للطباعة لأن رموز الطباعة المفيدة — عائلة الخط، ارتفاع السطر، تباعد الحروف، تركيبات الوزن — ليس لها أسماء واضحة مشتقة من القيمة كما لـ spacing.16. مفتاح fontSize.14 أقل فائدة بكثير من typography.body.small، وتوليد اسم سيئ أسوأ من عدم توليد اسم.

لذا النتيجة صادقة: إن كان ملف Figma يحتوي على متغيرات طباعة، تحصل على رموز طباعة. إن لم يحتوِ، تحصل على كائن فارغ ويُبلَّغ الوكيل عبر CONTEXT.md بأن تغطية الطباعة قد تكون جزئية.

// _meta.json
{
  "tokensSource": "inferred-from-frequency",
  "warnings": [
    "tokens-inferred-from-frequency"
  ]
}

يرى الوكيل هذا ويعرف أن يكون متحفظًا بشأن مراجع رموز الطباعة. يولّد كودًا احتياطيًا بقيم صريحة وتعليق TODO بدلًا من اختراع اسم رمز.

كيف يستخدم الوكيل tokens.json

قيد CONTEXT.md هو: "لا تُثبَّت قيم dp إذا كان رمز موجود ضمن ±2dp." تتعامل تسامح ±2dp مع التقريب. إذا كانت العقدة لها paddingLeft: 15 ويوجد spacing.16، يستخدم الوكيل spacing.16. إذا كان أقرب رمز هو spacing.24، لا مطابقة — يستخدم الوكيل القيمة الحرفية.

للألوان، المطابقة دقيقة على قيمة hex بعد التطبيع إلى أحرف صغيرة بـ 6 أرقام. #7F5CFE يطابق color.7f5cfe.

لنصف قطر الزاوية، نفس قاعدة ±2dp كالمسافات.

المخرج العملي لهدف Jetpack Compose يبدو هكذا:

// مع tokensSource = figma-variables
Surface(
    shape = RoundedCornerShape(Radius.radius8),
    color = Color.Brand.Primary
) {
    Column(
        verticalArrangement = Arrangement.spacedBy(Spacing.spacing16),
        modifier = Modifier.padding(horizontal = Spacing.spacing24)
    ) { ... }
}

// مع tokensSource = inferred-from-frequency (نفس المخرج البصري، نفس مراجع الرموز)
Surface(
    shape = RoundedCornerShape(Radius.radius8),
    color = Color.color7f5cfe
) { ... }

الأسماء المشتقة من القيمة أقل قابلية للقراءة. إنها لا تزال أفضل من القيم المُثبَّتة.

مقارنة مع نهج استخراج الرموز الأخرى

تُظهر لوحة "Inspect" الأصيلة في Figma القيم لكل عقدة. لا يوجد ملف رموز مُصدَّر. سيتعين عليك إنشاء واحد يدويًا أو استخدام إضافة كـ Tokens Studio. كلاهما يتطلب جهدًا من المصمم وصيانة مستمرة.

يستخرج figmascope الرموز آليًا في كل تصدير. إذا تغيّر الملف، أعد التصدير والرموز تعكس الحالة الراهنة. المقايضة هي أنه بدون متغيرات، الأسماء مشتقة من القيمة لا دلالية — لكنك تحصل على ملف رموز في كل مرة، بدون إضافة أو خطوة عمل إضافية.

يتطلب Tokens Studio (التكامل السابق مع Style Dictionary) من المصمم إعداد الإضافة والحفاظ على ملف JSON في ملف Figma ومزامنته. هذا الحل الصحيح لنظام تصميم ناضج. نهج figmascope هو الحل الصحيح للملفات التي لم تصل إلى هناك بعد، وهو معظم الملفات.

استخراج الرموز لقطة بأفضل جهد ممكن لما يوجد في الملف. إنه ليس بديلًا عن نظام تصميم قائم على الرموز أولًا. إنه الشيء الذي تستخدمه أثناء البناء نحو نظام كهذا.

ربط tokens.json بقاعدة الكود الخاصة بك

بنية JSON مسطّحة بما يكفي لتوليد كائن Kotlin أو وحدة TypeScript منها بشكل مباشر. سكريبت بسيط:

// tokens.json → كائن Kotlin (مُبسَّط)
const tokens = JSON.parse(fs.readFileSync('tokens.json', 'utf-8'));

let output = 'object Spacing {\n';
for (const [key, token] of Object.entries(tokens.spacing)) {
    const name = key.replace('spacing.', 'spacing').replace('.', '_');
    output += `    val ${name} = ${token.$value}.dp\n`;
}
output += '}';
// → val spacing16 = 16.dp

إن كنت تستخدم مسار رموز تصميم بالفعل، الصيغة الشبيهة بـ W3C قريبة بما يكفي لإدراجها في Style Dictionary بمحوّل مخصص لمفاتيح $value/$type.

بقية كيفية تفاعل الرموز مع IR مُغطّاة في IR لكل شاشة. لكيفية تفاعل الرموز مع سياق الوكيل الأشمل، انظر تشريح CONTEXT.md. لسير عمل تصدير رموز التصميم من البداية للنهاية، انظر تصدير رموز التصميم. لتصدير الرموز من ملف Figma الخاص بك، توجّه إلى figmascope.dev.