Skip to content
Astera Technology

Split an address block while preserving blank lines

Keep line structure and the raw block together.

Download complete case notes and answer keys ↓

Source contract and expected records

This is an original, fully synthetic mapping example. Inputs are plain, acyclic JSON-shaped records with the fields shown; the canonical shape and rejection codes belong to this example. Adapt the contract before using a different source.

The source is a nonempty address block with a nonempty country label. Accept LF and CRLF line breaks; reject a lone CR. Split into addressLines without trimming or removing blank lines, and retain sourceBlock. Country labels are opaque source text, not a geographical validation result.

Editable synthetic mapping cases
CaseInput record (JSON)Expected output (JSON)
Split supplied address block{"block":"Demo Tower\nUnit 7","countryLabel":"Example"}{"ok":true,"value":{"addressLines":["Demo Tower","Unit 7"],"countryLabel":"Example","sourceBlock":"Demo Tower\nUnit 7"}}
Reject absent address{"block":"","countryLabel":"Example"}{"ok":false,"error":"ADDRESS_EMPTY"}
Preserve interior blank line{"block":"Demo Tower\n\nUnit 7","countryLabel":"Example"}{"ok":true,"value":{"addressLines":["Demo Tower","","Unit 7"],"countryLabel":"Example","sourceBlock":"Demo Tower\n\nUnit 7"}}
Download editable CSV ↓

Run the local transformation

Run the complete example as a JavaScript module in Node.js. It contains the pure mapping function, all three inputs and literal expected outputs; assertions stop on a mismatch. A rejected case returns ok=false with an error code, rather than a partial canonical record.

Complete function and executable cases
import assert from 'node:assert/strict';

function addressLines(i){
  const fail=error=>({ok:false,error});if(!i||typeof i.block!=='string'||!i.block||typeof i.countryLabel!=='string'||!i.countryLabel)return fail('ADDRESS_EMPTY');
  if(/\r(?!\n)/.test(i.block))return fail('ADDRESS_BREAK');
  return {ok:true,value:{addressLines:i.block.split(/\r?\n/),countryLabel:i.countryLabel,sourceBlock:i.block}};
}

// Original synthetic cases; expected outputs are literal records.
const cases = [
  {
    "label": "Split supplied address block",
    "input": {
      "block": "Demo Tower\nUnit 7",
      "countryLabel": "Example"
    },
    "expected": {
      "ok": true,
      "value": {
        "addressLines": [
          "Demo Tower",
          "Unit 7"
        ],
        "countryLabel": "Example",
        "sourceBlock": "Demo Tower\nUnit 7"
      }
    }
  },
  {
    "label": "Reject absent address",
    "input": {
      "block": "",
      "countryLabel": "Example"
    },
    "expected": {
      "ok": false,
      "error": "ADDRESS_EMPTY"
    }
  },
  {
    "label": "Preserve interior blank line",
    "input": {
      "block": "Demo Tower\n\nUnit 7",
      "countryLabel": "Example"
    },
    "expected": {
      "ok": true,
      "value": {
        "addressLines": [
          "Demo Tower",
          "",
          "Unit 7"
        ],
        "countryLabel": "Example",
        "sourceBlock": "Demo Tower\n\nUnit 7"
      }
    }
  }
];
for (const sample of cases) {
  const actual = addressLines(sample.input);
  assert.deepEqual(actual, sample.expected);
  console.log(sample.label, JSON.stringify(actual));
}
Download runnable example ↓

Work through the boundary

Why is the blank line between Demo Tower and Unit 7 retained?

Show the worked answer

It is part of the supplied layout. The output has three lines, with an empty second string; sourceBlock retains the original breaks for reconstruction.

Related resources