Skip to content

fix: escape special characters in Figma property names in generated template code#380

Open
jmlweb wants to merge 1 commit intofigma:mainfrom
jmlweb:fix/escape-single-quotes-in-property-names
Open

fix: escape special characters in Figma property names in generated template code#380
jmlweb wants to merge 1 commit intofigma:mainfrom
jmlweb:fix/escape-single-quotes-in-property-names

Conversation

@jmlweb
Copy link
Copy Markdown

@jmlweb jmlweb commented Mar 25, 2026

Summary

Figma property names containing apostrophes (e.g. Tab's number) produce broken JavaScript when interpolated into single-quoted string literals in the generated template code. The Figma Code Connect panel fails to render the example, even though figma connect publish succeeds without errors.

Root cause

intrinsicToString() in cli/src/connect/intrinsics.ts interpolates figmaPropName directly inside single-quoted JS template literals without escaping:

// Before (broken for names containing apostrophes):
return `${selector}.__properties__.string('${args.figmaPropName}')`
// Generates: string('Tab's number')  — syntax error

Similarly, valueMappingToString() wraps enum mapping keys in double quotes without escaping internal double quotes.

Fix

  • Rename replaceNewlinesescapeForSingleQuotedString with correct escaping order (backslashes first, then quotes, then newlines)
  • Add escapeForDoubleQuotedString for double-quoted contexts (mapping keys, layer names, className strings)
  • Apply escapeForSingleQuotedString to all figmaPropName interpolations in intrinsicToString (String, Instance, Boolean, Enum, Slot)
  • Apply escapeForDoubleQuotedString to Children layer names, ClassName strings, TextContent layer names, NestedProps layer names, and valueMappingToString keys

Affected intrinsic types

Intrinsic Quoting context Escaping applied
String, Instance, Boolean, Enum, Slot '${figmaPropName}' escapeForSingleQuotedString
Children "${layerName}" escapeForDoubleQuotedString
ClassName "${className}" escapeForDoubleQuotedString
TextContent '${layer}' escapeForSingleQuotedString
NestedProps "${layer}" escapeForDoubleQuotedString
valueMappingToString keys "${key}" escapeForDoubleQuotedString

Reproduction

  1. Create a Figma component with a property named Tab's number
  2. Write a Code Connect file using figma.string("Tab's number")
  3. Run figma connect publish — succeeds
  4. Open the component in Figma → Code Connect panel → example does not render

Test plan

  • Added SpecialCharProps.figma.tsx test fixture with apostrophes in figma.string, figma.enum (prop name + mapping key with apostrophe), figma.boolean, and double quotes in an enum mapping key
  • Added corresponding SpecialCharProps.expected_template validating escaped output
  • All 47 existing parser tests continue to pass
  • New test validates both templateData (raw prop names preserved) and template (escaped output)

🤖 Generated with Claude Code

…e code

Figma property names containing apostrophes (e.g. "Tab's number") produce
broken JavaScript when interpolated into single-quoted string literals in
the generated template code. The Figma panel fails to render the example
even though `figma connect publish` succeeds without errors.

Before this fix, `intrinsicToString()` generated:
  figma.currentLayer.__properties__.string('Tab's number')
which is a syntax error — the apostrophe closes the string literal.

After this fix:
  figma.currentLayer.__properties__.string('Tab\'s number')

Changes:
- Rename `replaceNewlines` to `escapeForSingleQuotedString` with correct
  escaping order (backslashes first, then quotes, then newlines)
- Add `escapeForDoubleQuotedString` for double-quoted contexts
- Apply escaping to all `figmaPropName` interpolations in `intrinsicToString`
- Apply escaping to layer names and mapping keys in double-quoted contexts
- Add test covering apostrophes in string/enum/boolean property names and
  double quotes in enum mapping keys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant