Reported July 2026
Figmastack

Rich Text Parser Part 3 (Depth Tokens)

Reported by candidates from Figma's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.

Get StealthCoderRuns invisibly during the live Figma OA. Under 2s to a working solution.
Founder's read

Figma's Rich Text Parser Part 3 showed up in July 2026 reports, and it's the twist that breaks people who hardcoded Part 2. The whole solution hinges on a stack of open groups. Tokens are now depth/word pairs with no brackets, so you track the current depth, open groups when it rises, and close them when it falls. It's the last piece of a 3-part set, and you only get it if you see depth as stack size. If you blank on the live OA, StealthCoder runs invisibly as a safety net, but the pattern is small enough to own tonight.

The problem

🐝 Hi there! The description you are currently reading is one part of a 3-part Figma interview set. It is highly recommended to read ALL THE PARTS before coding as parts build on top of each other 🐳
Rich Text Parser Part 1 (Validate Tokens) 🦔
Rich Text Parser Part 2 (Parse Nested Groups) 🐹
Rich Text Parser Part 3 (Depth Tokens) 🦚
At Figma, documents are stored as nested structures: a paragraph can contain text runs and nested groups, which can themselves contain more groups. You are working with a small text format that describes structures like this. This set reconstructs a real ~45-minute Figma coding screen, part by part.
Part 3. This was the final twist of the real interview. After the Part 2 parser passed, the interviewer swapped the tokenizer for a different implementation and asked for the same result. The new tokenizer returns a flat list in which every word is preceded by its nesting depth: tokenize("(a,(b),c)") now returns [1, 'a', 2, 'b', 1, 'c']. There are no bracket tokens anymore.
Implement readRichText(tokens) that produces the same serialized nested structure that Part 2 produced, from this new token format. On FastPrep the flat list arrives as string tokens: depths appear as strings such as "1", each followed by its word.
Rules of the depth encoding.
depths are positive integers; the first depth may be greater than 1
between consecutive words the depth may rise or fall by more than 1: each unit of rise opens one new group, each unit of fall closes one
consecutive words at the same depth are siblings in the same group, and a word that returns to a still-open depth joins that open group
this encoding cannot represent empty groups, so none appear
Output format. Return the parsed document as a Python-style list string:
a group serializes as [ … ] with children joined by a comma and a single space
words are wrapped in single quotes
the return value is the serialization of the document: the list of all top-level items. A document that consists of one group therefore starts with two brackets, e.g. [['a', 'b', 'c']]
In Python, str(nested_list) produces exactly this format.

Function
readRichText(tokens: String[]) → String

Examples
Example 1
tokens = ["1", "a", "1", "b", "1", "c"]
return = "[['a', 'b', 'c']]"
All words have depth 1, so they belong to the same top-level group: ['a', 'b', 'c']. The full parsed document is [['a', 'b', 'c']].
Example 2
tokens = ["1", "a", "2", "b", "1", "c"]
return = "[['a', ['b'], 'c']]"
This is the Part 3 source example for tokenize("(a,(b),c)"). The word b has depth 2, so it becomes a nested group between a and c.
Example 3
tokens = ["3", "a", "2", "b", "1", "c"]
return = "[[[['a'], 'b'], 'c']]"
This corresponds to the source example read_rich_text(tokenize("(((a)b)c)")) from Part 2. The first depth is 3, so a sits inside three groups; the depths then fall to 2 and 1, closing one level each time. Together with the outer document list the answer has four leading brackets.
Example 4
tokens = ["1", "a", "3", "b"]
return = "[['a', [['b']]]]"
Only words carry depth labels, so the depth can jump from 1 straight to 3: two new groups open at once and b lands inside both.

Constraints
0 <= tokens.length <= 5000, always an even number: alternating depth and word
depths are decimal strings between 1 and 50
words are lowercase alphanumeric with at most 10 characters

Reported by candidates. Source: FastPrep

Pattern and pitfall

Keep a stack of lists. Start with a root list for the document. For each depth/word pair, compare the depth to the stack's current open-group count (stack size minus the root). While the stack is smaller than the depth, push a new list and append it to its parent. While it's larger, pop. Then append the word to the top list. That handles jumps of more than 1 in either direction, like going from depth 1 to 3 in Example 4, which opens two groups at once. The pitfall is the first depth. It can be greater than 1, so don't assume you start at 1. Another trap is the output. The document is a list of top-level items, so a single group gets double brackets. Build real nested lists, then serialize with Python's str, or write a small recursive serializer with quotes and ', ' joins. StealthCoder is the hedge if the stack logic slips under pressure.

Memorize the pattern. If you can't, run StealthCoder. The proctor sees the IDE. They don't see what's behind it.

If this hits your live OA

You can drill Rich Text Parser Part 3 (Depth Tokens) cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Made by an engineer who treats the OA as theater. If yours is tonight, you don't have time to grind. You have time to hedge.

Get StealthCoder

Related leaked OAs

⏵ The honest play

You've seen the question. Make sure you actually pass Figma's OA.

Figma reuses patterns across OAs. Made by an engineer who treats the OA as theater. If yours is tonight, you don't have time to grind. You have time to hedge. Works on HackerRank, CodeSignal, CoderPad, and Karat.

Rich Text Parser Part 3 (Depth Tokens) FAQ

What's the trick in Figma's Rich Text Parser Part 3?+

Treat depth as stack size. Keep a stack of open lists with the document root at the bottom. Push new lists while the stack is shallower than the token's depth, pop while it's deeper, then append the word to the top list. Every case in the examples falls out of that.

How do I handle depth jumps like 1 straight to 3?+

Use a while loop, not an if. Each unit of rise opens one new group, so a jump from 1 to 3 pushes two nested lists before the word lands. The same goes for falls: each unit of drop pops one list. Example 4 tests exactly this.

Why does the output start with two brackets for one group?+

The return value serializes the document, which is the list of all top-level items. A single group is one item inside that list, so you get [['a', 'b', 'c']]. Your root list is the outer bracket, and the first group is the inner one.

Do I need to read Parts 1 and 2 first?+

Yes, skim them. Part 3 must produce the same serialized structure as Part 2, just from a different token format. Knowing the output rules and the bracket-based nesting helps you check your depth-based result against the Part 2 examples quoted in the problem.

How do I prepare for this in 48 hours?+

Hand-trace Examples 2, 3, and 4 with a stack until it's automatic. Then code it once, including the string conversion of depths and the serialization. Test the empty input, which should return an empty document, and a first depth above 1. That covers most of what this problem can throw at you.

Problem reported by candidates from a real Online Assessment. Sourced from a publicly-available candidate-aggregated repository. Not affiliated with Figma.

OA at Figma?
Invisible during screen share
Get it