← Back to challenges

SVG Path Data Parser

JavaScriptHardregexstringsarrays

Instructions

A <path> element can usually be found inside an <svg> element and has an attribute d that represents the definition of the outline of a shape.

A brief summary about this attribute:

  • It contains commands (letters) and coordinates (numbers)
  • All instructions are expressed as one character (e.g., a moveto is expressed as an M).
  • Superfluous white space and separators such as commas can be eliminated (e.g., M 10 10 L 20 20 contains unnecessary spaces and could be expressed more compactly as M10 10L20 20).
  • The command letter can be eliminated on subsequent commands if the same command is used multiple times in a row (e.g., you can drop the second L in M 10 20 L 20 10 L -10 -20 and use M 10 20 L 20 10 -10 -20 instead).

Your job is to build a parser that will convert this string in an array of commands, where each array element is an object with the command letter and an array of parameters.

Examples

pathDataParser("") ➞ []

pathDataParser("M 0 0") ➞ [{command: 'M', parameters: [0, 0]}]

pathDataParser("M 1 1.5 L 0 1.5 0 0.5 1 0.5 0.5 0 0 0.5 1 1.5 1 0.5 0 1.5" ➞ [
  {command: "M", parameters: [1, 1.5]},
  {command: "L", parameters: [0, 1.5, 0, 0.5, 1, 0.5, 0.5, 0, 0, 0.5, 1, 1.5, 1, 0.5, 0, 1.5]}
]

pathDataParser("M 0,1 h 1 v -1 h 1 v 1 h 1 C 2,1 3,3 1.5,3 C 0,3 1,1 0,1 z" ➞ [
  {command: "M", parameters: [0, 1]},
  {command: "h", parameters: [1]},
  {command: "v", parameters: [-1]},
  {command: "h", parameters: [1]},
  {command: "v", parameters: [1]},
  {command: "h", parameters: [1]},
  {command: "C", parameters: [2, 1, 3, 3, 1.5, 3]},
  {command: "C", parameters: [0, 3, 1, 1, 0, 1]},
  {command: "z", parameters: []}
]

Notes

  • Return an empty array if no commands are found (example #1)
  • The z (or Z) command is the only one without parameters, in this case return an empty array (see last command of example #4)
  • The parameters array contains numbers, not strings, so you'll have to convert them
  • Sometimes numbers can be very compressed to save space, let's look at some examples that might trip you up:
    • Decimal numbers can start with a dot: .4 is the same as 0.4
    • If a negative number comes after another number, the space is optional: 0-4 is equal to 0 -4
    • Multiple decimal numbers in a row can be very tricky, remember that a number CAN NOT have more than 1 dot, so this: 1.2.34 is actually 2 different numbers: 1.2 and 0.34
  • Some examples have commas, some do not, some have multiline strings, some are a single line, remember to take into account all valid cases! Check out the tests tab to find out more.
javascript
Loading editor…
⌘ ↵ to run
Walks through the solution with reasoning and edge cases.