# Changelog Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). A release's `Breaking` section comes first and names each rejected spelling with its replacement, and each removed path, column or flag. ## [Unreleased] ### Added - Step up: `..` after a row steps up to the row its link column names, so `{/city[Oslo]..country.name}` renders `Norway`, and `.` after it steps down again, drawing afresh. `New` refuses a `..` naming anything but the parent table, and a selector after a `..`. - A path, given to `Fake` or referenced in a template, may not read into a level carrying a `repeat`, and `List` advertises no such path: where `x` carries `"repeat": 3`, `Fake("x.a")` fails naming the level `x`, and `Fake("x")` renders it whole. - Every `{…}` draws afresh, and a name is the one way to keep a pick: `{p.a} {p.b}`, `{w} {uppercase(w)}` and `{/person.first} {/person.last}` are two draws each, which `{p as q}{q.a} {q.b}` and `{/person as n}{n.first} {n.last}` make one. `{/misc.territory as t}` binds one row of `misc.territory` to `t` and prints nothing; `{t}`, `{t.capital}` and `{lowercase(t.name)}` read that one row. `{x as n}` binds a reference, a sibling field or a path into one; a name lives in the category binding it, and picks again on every iteration of a `repeat`, or every draw of a choice item, binding it. A struct's tags share its names, `{/sv_SE.person as p}{p.first}` beside `{p.sex}`. A name is a `{calc()}` operand: `{/misc.coordinate.lat as lat}{calc(lat * 60)}`. What `New` refuses is listed under [Names](README.md#names). - First release: the CLI, the library and the shipped data set. - The CLI renders exactly the template on its stdin, `echo '{/sv_SE.person} hihi' | fejkdata`, and adds nothing under `--format text`: `echo`'s newline ends the render, and `--separator` defaults to empty. Whitespace around a JSON object, array or string template is dropped, and a bare number or boolean is a format string, printed as written. A lone reference, `{/users}`, is the record `users` under `--format`. An argument other than a flag, or nothing piped in, exits 2; an empty or blank stdin is a format string, and renders as sent. - A template or data file loads whatever is well-formed and means one thing, even where part of it does nothing: a default written out; a one-item choice; an object holding only a format; a constant sample such as `{int(5,5)}`; a `weight`, `separator` or `datatype` where it does nothing; a name nothing reads; a repeated item, which counts as written; a weight of `0`, which is never drawn; a `repeat` or count of `0`, which renders nothing; `+5`, `05` and `-0`; and a reference into the category it sits in. A rows file no category names is ignored. `New(WithDataFS())` loads no data, and renders templates that read none. The CLI's `-n` takes `0`; `--list` ignores `--repeat`, `--separator`, `--format` and `--table`, and `--table` is ignored without `--format sql`. - Table categories: a category JSON naming a `rows` TSV beside it, with the options `key`, `name`, `weight` and `parent`; a path selects a row by key or name, `misc.territory[SE]`, and descends to a linked table by name, one path drawing each row inside the row above it. `rows` is an option, so no template may carry a field of that name. A `name` without a `key` resolves inside the table's `parent`. Refused at `New`: a `name` without a `key` or a `parent`, a name repeating inside one parent row, a name spelling another row's key, and a table named like a column of any table above it. - `misc.territory`, `misc.currency`, `misc.language`, `misc.httpstatus` and `misc.mimetype` are tables. `misc.territory` is every ISO 3166-1 territory that has a capital, a currency and a TLD, with the columns `calling-code`, `capital`, `country`, `currency`, `flag`, `languages`, `numeric` and `tld` added, `country` holding the alpha-2 code of the sovereign state it belongs to and its own where it is one; `misc.currency` the current ISO 4217 currencies with a minor unit, with `decimals` and `numeric` added, and its symbols from CLDR; `misc.language` every ISO 639-2 entry carrying a 639-1 code, with a `code3` column holding its 639-2/T code; `misc.httpstatus` each code the IANA registry lists with a plain reason phrase; and `misc.mimetype` each type mime-db records as IANA-registered and gives a filename extension. `DATA-LICENSES.md` lists each source. - `misc.timezone`, `misc.car` and `misc.useragent` are tables too. `misc.timezone` is every zone tzdb `zone.tab` gives a shipped territory, with `offset` holding the zone's standard UTC offset and `territory` linking to `misc.territory`, so `misc.territory[SE].timezone` draws `Europe/Stockholm`; zones of a territory `misc.territory` does not ship, Antarctica's among them, and the constant `UTC` are gone; spell that one as the text `"UTC"`. A `weight` column carries the population GeoNames records in each zone, so a draw favours the zones people live in. `misc.useragent` is the top-user-agents desktop and mobile lists with `browser`, `device` and `os` columns. `misc.car` keeps its makes and models in a `make` and a `model` column. - `misc.httpmethod`, `misc.protocol` and `misc.port` are IANA's registries as tables. `misc.httpmethod` is the eight methods RFC 9110 defines and PATCH, carrying `safe` and `idempotent` as `true` or `false`; `misc.protocol` the keyword, its `number` and its `name`, selectable by either; `misc.port` renders a TCP port number, with the IANA `service` name beside it, keeping the first service the registry describes for a port so a number selects one row. - `misc.tld` is the IANA root zone as a table: every delegated TLD keyed with its leading dot, `.se` and `.xn--p1ai`, the register's `type` beside it, and a `unicode` column holding the form the register displays, so `misc.tld[.рф]` selects the row `.xn--p1ai` renders. A delegation the register marks "Not assigned" does not ship. - `misc.loglevel` is the eight syslog severities: the `keyword` a configuration writes, `err` and `info`, keyed by the numerical `code` a PRI encodes and selectable by either, with the `severity` RFC 5424 spells beside it. - `geo.SE` and `geo.US`: five linked tables per country, `region`, `municipality`, `locality`, `postal-code` and `street`, weighted by population and address counts and built from SCB, GeoNames, Trafikverket NVDB and the US Census Bureau, and an `address` record binding one locality and drawing its street and postal code inside it. `sv_SE.address` and `en_US.address` bind those records once, so `en_US.address.street` no longer carries `name` and `suffix`, and a locale's `address` reads its country's `geo` module. Every Swedish postort the import can place and give a street ships with all its streets. Of the US incorporated places that hold most of some postal code's land, every state capital but Honolulu, every place of 100,000 or more, and a tenth of the rest drawn by population down to villages of a hundred people ship, so a smaller city may be missing; each carries a quarter of its streets, at least ten. - `{date(from,to,'layout')}` and `{time('layout')}`: a second between two days, or within one, in a single-quoted Go layout, drawn in UTC; `from` may equal `to`. `sv_SE.date`, `en_US.date`, `sv_SE.time` and `en_US.time` render through them, so `date.year`, `date.month`, `date.day`, `time.hour`, `time.minute`, `time.minute.t`, `time.sec` and `time.ampm` are no longer paths — a part of a date is now its own `{date(…,'2006')}`. `misc.datetime` is an RFC 3339 instant. - `sex`, `first-name` and `last-name` tables in `sv_SE` and `en_US`, weighted by bearers from SCB, the SSA and the Census Bureau; `first-name` links to `sex`, and a name both sexes carry is a row under each. `person` binds one first name and reads its sex through it, and its columns are `first`, `last`, `prefix` and `sex`; `person.femalefirst` and `person.malefirst` are no longer paths — draw `sex[f].first-name` and `sex[m].first-name` instead. `en_US.title` links to `sex` as well, so `en_US.person.prefix` draws `Mr` or `Ms` without contradicting the record's `sex`; `sv_SE.title` is an unsexed table of the same shape. - `sv_SE.personnummer` and `sv_SE.samordningsnummer`, Skatteverket's test series from a `sv_SE.birth-number` table under `sex`, in place of `sv_SE.ssn`, whose `ssn.mmdd`, `ssn.mmdd.m` and `ssn.mmdd.d` go with it. `en_US.ssn` now draws the ranges the SSA assigns and carries the columns `area`, `group` and `serial`, so `echo '{/en_US.ssn}' | fejkdata --format csv` writes a header where it used to fail; `en_US.itin` is new and carries the same three. `person.prefix` is null where a person has no title, where it used to be an empty string, so `--format sql` writes `NULL` and a `string` struct field reading it becomes `*string`. - `en_US.phone-exchange` draws the three digits after a US area code evenly from the codes NANPA may assign: `200` to `999`, except `211`, `311` … `911`, `555`, `950`, `958`, `959` and `976`. `en_US.phone` draws its `exchange` from it. - `ErrNoColumns` is exported, so a caller can tell the one record fence a path can answer from the rest. - An error names a spelling that runs: a layout is named single-quoted and free of its own quotes, a row of a table with no key is named as the path that selects it, `sv_SE.sex[f].first-name[Kim]`, and a category with no columns names the record that gives it one. - The shipped data comes in Go packages, one per module, each exporting `FS`: `github.com/larvit/fejkdata/data/en_US` (package `enus`), `…/sv_SE` (`svse`), `…/misc`, `…/geo/SE` (`geose`) and `…/geo/US` (`geous`). `data.Modules()`, from `github.com/larvit/fejkdata/data`, lists every one, and the CLI carries them all. Each package's `Modules()` returns its `FS` and every module it reads: `svse.Modules()` holds the Swedish places too. `New` loads the modules `WithDataFS(modules...)` names and the folders `WithDataPath` names, and fails, naming `WithDataFS`, where no such option is given. A manifest's `namespace` mounts its source under a dot path. - A data source whose root holds a `.fejkdata.json` manifest with an `index` loads each category on the first call reaching it, as each shipped module does. Data failing to load, in `New` or on that first call, gives an error matching `ErrLoad`, and the CLI exits 1. A source without an index loads in `New`, with the indexed categories it reads. Every other shipped category loads on the first call reaching it, so one your replacement breaks fails there.