Documention for template authors

This page contains documentation for template authors. Documentation on how to call the Murasaki API is at the start page. Documentation on how to develop in README.md.

Murasaki compiles PUG templates, adding a number of useful helper functions and mixins.

All available helper functions and mixins are listed in the menu to the left.

Example template:

    h1 #{winner} vann jämn backhoppning
    p #{winner} från #{territory(winner_nation)} vann backhoppningen i #{t(venue)} efter en rafflande slutstrid. Slutpoängen blev #{number(points)} poäng.
    p Det återstår nu #{numberPretty(remaining)} #{pl(remaining, "tävling", "tävlingar")} i världscupen den här säsongen.

Example data:

{
  winner: "Ryoyu Kobayashi",
  winner_nation: "JP",
  venue: "Vienna",
  points: 266.6,
  remaining: 2
}

Generated HTML:

    <h1>Ryoyu Kobayashi vann jämn backhoppning</h1>
    <p>Ryoyu Kobayashi från Japan vann backhoppningen i Wien efter en rafflande slutstrid. Slutpoängen blev 266,6 poäng.</p>
    <p>Det återstår nu två tävlingar i världscupen den här säsongen.</p>

Further reading

Changelog

  • 11.2.0

    • [NEW] style option to territory* methods, allowing e.g. both legal and common names.
  • 11.1.3

    • [BUG] Init Options class with optionDefaults, making them work everywhere
    • [INTERNAL] Cap Node version at 24, as c8 has a bug with Node 25. Only affects testing.
  • 11.1.2

    • [BUG] Fix PRB in optionDefaults
  • 11.1.1

    • [INTERNAL] Date list parsers (for e.g. yearList()) will now raise an error if the list contains null values, to avoid harder to debug errors down the pipe.
    • [DOC] Various fixes
  • 11.1.0

    • [BREAKING] Default for level option is now null (was 1)
    • [BREAKING] list*() methods will try to auto determine level unless explicitly set.
    • [NEW] All list functions will now try to respect level options
    • [INTERNAL] Refactored, more robust list level handling
  • 11.0.0

    • [MAJOR-BREAKING] We now require an explicit locale to be set when using a territory dependant methods. To migrate change any sv to sv-SE, sv-AX or sv-FI, etc. Calling these methods without a locale will throw an error
    • [BREAKING] interval*() have new behaviour for equal-ish dates. intervalMonth("2025-03-01", "2025-03-03") will now return ”March 2015”
    • [DATA] CLDR 48
    • [NEW] duration*Short() for abbreviated temporal durations
  • 10.10.0

    • [NEW] largeNumberChange(), millionsChange() and billionsChange()
    • [NEW] largeNumberChangeShort(), millionsChangeShort() and billionsChangeShort()
  • 10.9.0

    • [NEW] largeNumberShort(), millionsShort() and billionsShort()
    • [INTERNAL] Remove some unnecessary casting
  • 10.8.0

    • [NEW] text() method, like void but escapes <, > and &.
  • 10.7.1

    • [NEW] Add default param support to even more date functions
    • [DATA] Add soft hyphen in algorithmic Swedish demonyms
  • 10.7.0

    • [NEW] Add default param support to more date functions
    • [NEW] missing days*(), monthDays*(), yearMonthDays*() methods
    • [INTERNAL] remove some duplicated date argument parsing
  • 10.6.0

    • [NEW] void() method, to trigger pre- and postprocessing
    • [REMOVED] Removed support for deprecated Temporal.PlainDateTime objects in time functions.
    • [INTERNAL] Rewrite timezone handling to folow the latest Temporal proposal
    • [DOC] equalAt type
  • 10.5.0

    • [DATA] CLDR 47, see https://cldr.unicode.org/downloads/cldr-47
    • [NEW] dayPeriod given a time, return e.g. ”in the evening”
  • 10.4.0

    • [NEW] age*() returns an age given a birthdate and a reference date (default .today)
  • 10.3.1

    • [DATA] "fi01" as an alias for "ax" in preparation for CLDR 47.
    • Tweak territory look-up methods to make them slightly faster.
    • Bundle Swedish Words 2.10
  • 10.3.0

    • [NEW] add lowerFirst()
  • 10.2.1

    • [BUG] Include locale settings in cache key for method cache
    • [BUG] Include optionDefaults in cache key for method cache
    • [BUG] Exclude relative date methods from method cache
  • 10.2.0

    • [BREAKING] Var().some() and Var().every() will return Var objects, like Var().map() etc
    • [DATA] CLDR 46 through cldr 7.7.0
  • 10.1.2

    • [DOC] Fix currencies namespace error
  • 10.1.1

    • [NEW] Allow some decimal digits options in currency formatting
    • [BUG] Avoid an edge case pass-by-reference bug in options parsing
    • [DOC] Move currency methods to its own namespace
    • [INTERNAL] Unified currency code parsing
  • 10.1.0

    • [NEW] currencyName() and currencySymbol()
    • [NEW] currency() and currencyShort()
    • [DOC] More number options
  • 10.0.1

    • [BUG] Fixed an ugly bug with changeInteger(-0.5), introduced in 9.4.0
    • [DATA] Added more sv-SE demonyms
  • 10.0.0

    • [BREAKING] Renamed option precisionHead => significantDigits
    • [NEW]: Some methods can now act as getters with a default variable. (This was previously experimentally implemented for some territory functions). E.g. territoryShort as a shortcut for territoryShort(DefaulRegionVar)
    • [NEW] Make any iterable work in list arguments
    • [ERRORS] Add error handling for non-valid list arguments
    • [INTERNAL] Move basic number formatting to Intl (for non-algorithmic numbering systems only)
    • [INTERNAL] Use intl-format-cache from format.js for Intl caching
    • [INTERNAL] Partially revert Var changes from 9.2, again monkey-patching array methods.
  • 9.4.0

    • [NEW] permille*() methods
    • [NEW] percentShort*() and percentLong*() methods for printing a whole text string, e.g. “15 percent”. Long variants use local data.
    • [NEW] permilleShort*() and permilleLong*() methods
    • [NEW] changePercentShort*() and changePermilleShort*()
    • [NEW] precision and precisionHead options now work in change*()
    • [BUG] Fixed an issue where local json data could sometimes be overwritten by defaults while using subkeys
    • [INTERNAL] Started migration of numberformatting to ICU Intl. All change*() method now use Intl. There could be edge cases where behaviour around e.g. rounding and conflicting options has changed.
  • 9.3.0

    • [NEW] Add style: "range" to yearList*() functions, for output like “2019 and 2023-2026”
    • [NEW] Allow passing partial dates ("2024" or "2024-02") to some date functions, such as year(). This used to throw an error.
    • [DOC] Started adding custom types to doc, to better describe possible inputs
    • Style default changed to "default". standAlone is now an alias for default in date functions. This change should be backwards compatible.
  • 9.2.1

    • [DOC] demonym() docstr fix
  • 9.2.0

    • [NEW] demonym(), using local data. Only available for sv
    • [NEW] Add missing date list methods for completeness: dateListOr(), dayMonthListOr(), monthYearListOr() and yearListOr(). Note that these methods are deduplicating by design, and need no -Unique-variants.
    • [BUG] Make caching work with arrays inside Var's, and with Var's inside arrays
    • [DOC] Groups territoryList*() with territory() methods under “text”.
    • [INTERNAL] New argument parser for grammatical form, e.g. case, to unify parsing across methods
    • [INTERNAL] Var() will cast primitive Array members to Var on creation, rather than in patched array methods. The following edge case will no longer work: Val([1, 2, 3]).map(v => "x" + v)[0].upper()
    • [INTERNAL] Var() will return early when passed a tF Var object
  • 9.1.0

    • [NEW] yearList() method
    • [INTERNAL] Avoid crashing when trying to cache un-serializable arguments.
    • [INTERNAL] Don't try to serialize t(). We don't know what unholy objects the users might pass in...
  • 9.0.4

    • [INTERNAL] Handle undefined arguments creating cache key
    • [INTERNAL] Don't cache errors
  • 9.0.3

    • [INTERNAL] Use normalized cache signature in chained functions
    • [INTERNAL] Revert caching on depth > 1
  • 9.0.2

    • [INTERNAL] Allow Cache to use user-provided cache, falling back to MethodCache
  • 9.0.1

    • add missing MethodCache doc
    • [INTERNAL] Tweak tF initiation
    • [INTERNAL] Allow method cache on depths 1 AND 2
  • 9.0.0

    • [NEW] Experimental support for simple method caching mechanism, using a key/value data store
    • [NEW] Exposing a simple in-memory cache class as a dev/fallback cache: MethodCache
    • [INTERNAL] Exclude debug method from method decoration
  • 8.25.2

    • [DATA] sv: Storuman compound form
  • 8.25.1

    • [BUG] Add grammar files missing in last release
  • 8.25.0

    • [NEW] distance*() methods, for “road distances” (e.g. “fem mil”)
  • 8.24.0

    • [BUG] Emit readable error messages on invalid input to territory/dateList*() methods
    • [BREAKING] Revert 8.23 changes to negative approximations logic, and disable support alltogether. Negative number support had super-weird effects on various edge cases. Negative numbers will now throw an error in all approximate*() methods, as they are not well defined there.
    • [BREAKING] largeNumber*() and friends now default to a non-breaking space in e.g. “12 millions”.
  • 8.23.0

    • [DATA] CLDR v45, see https://cldr.unicode.org/downloads/cldr-45
    • [NEW] largeNumber- will try to handle negative numbers
    • [BREAKING] Reversed logic for negative approximations: -1010 is now ”more than minus one thousand”
  • 8.22.1

    • Only treat strings as naked option
  • 8.22.0

    • [BREAKING] Remove deprecated case option support
  • 8.21.3

    • [BUG] Avoid overwriting form with invalid case values
    • Don't add empty arrays to allowedOptionValues
  • 8.21.2

    • [INTERNAL] Run territory hooks for each member in territoryList arguments
  • 8.21.1

    • [BUG] Fix pbr bug in options alias
    • [INTERNAL] Added argument type for region lists to make plugin hooks work as expected
  • 8.21.0

    • [NEW] Added adjunct as a territory declination
    • [NEW] territoryList(), for lists like ”Mora, Ludvika och Smedjebackens kommuner”
    • [NEW] territoryListUnique()
    • [NEW] territoryListOr()
    • [NEW] territoryListOrUnique()
    • [DEPRECATION] The case option used in territory*() has been renamed to the more general form. Case is kept as an alias, but marked as deprecated
    • [DEPRECATION] Date list method are renamed to align with naming convention. Old names are kept as aliases, but marked as deprecated
      • listDates() renamed dateList()
      • listDayMonths() renamed dayMonthList()
      • listMonthYears() renamed monthYearList()
    • [DATA] Added some missing SE territoriy variants in en
    • [DATA] Added JP territoriy variants in sv, due to inconsitencies in CLDR (for test suits)
    • [DATA] Added JP territoriy variants in ja for test suits
  • 8.20.1

    • Make sure to pass by refrence in optionsBeforeParseAll
  • 8.20.0

    • Added optionsBeforeParseAll hook for plugins
  • 8.19.1

    • Additional approximate*() finetuning
    • Tweaks to equalAt option, using dynamic values (e.g. Math.log(1.3) / Math.log(val) for large numbers).
    • [DOC] Improved docstrings for a lot of number functions
    • [DOC] Added missing approximateMultiplier*()
  • 8.19.0

    • [BREAKING] semester() renamed semesterYear() for consistency
    • [NEW] Added semester()
    • [NEW] Added approximateInteger*() as an alias for approximately(X, {decimalDigits: 1})
    • Finetuned default values for precision in approximate*()`
    • approximate*() will now try and take decimalDigits into account in pattern selection
    • [DOC] Fix approximately doc strings
    • [DOC] Fix turnOfYear doc strings
  • 8.18.0

    • [NEW] Added approximateLargeNumberText() and approximateLargePretty() variants
    • [BUG] Fixed a number of bugs in approximate*() for small numbers
    • [BUG] precision: 0.1 and similar values are now respected
    • [BUG] Fixed rounding bugs in approximateLargeNumber()
    • [BUG] approximateLargeNumber*() methods now respect largeNumberLimit defaults, as they should
    • approximate*() now handles negative numbers like it would positive (even though that rarely makes makes). This made it possible to cleanup handling of some edge cases.
    • Hard coded defaults for approximate*() precision option for small values, for more intuitive results.
  • 8.17.3

    • [DATA] SE-2513 sv case fix.
  • 8.17.2

    • [DATA] SE-2514 sv case fix.
  • 8.17.1

    • [BUG] clean up unnecessary postinstall script
  • 8.17.0

    • [NEW] fraction- takes custom rules in the options (like approximately): {"1/2": "varannan"}
  • 8.16.1

    • [DATA] Fix Swedish genitive form for 'Strängnäs'
    • Doc fixes
  • 8.16.0

    • [BREAKING] Default value for denominator is now "pretty"
    • [DEV] eslint migrated to version 9 (this is a major update)
    • More explicit error messages in some places
  • 8.15.0

    • [NEW] Hacky support for approximateLargeNumber()
    • [NEW] quadrimester()
    • [NEW] semester()
    • trimester as alias for quarter
    • use proper year formatting in quadrimester() and semester().
    • allow more complex approximately*() helper functions, to prepare for future refactoring
    • various doc fixes
  • 8.14.0

    • [NEW] Added missing relativeMonthYear*() methods for consistency, effectively the same as adding month() and relativeYear() together, following locale date patterns.
    • [NEW] Added relativeLimit option to relative*() methods, to force absolut grammar beyond a certain number of years or months (e.g. 'mars i fjol' but 'mars 1998'). See also since*() for a somewhat similar family of methods. Can be a number, or a dictionary of unit/number.
  • 8.13.1

    • [BUG] Make sure approximately*() doesn't crash on invalid options syntax.
  • 8.13.0

    • [BREAKING] list*() methods now cast members to string if no other formatter is assigned
    • We now use String.isWellFormed() for input and String.toWellFormed() for output to ensure strings are well behaved.
  • 8.12.1

    • [DATA] Swedish compound form of Bjuv is now ”Bjuvs”
  • 8.12.0

    • [NEW] daysInMonth() returns, as a number, the number of days in a month
  • 8.11.1

    • [DATA] Swedish compound form for Uppland Väsby is now Väsby-
  • 8.11.0

    • [BREAKING] title() now handles all Unicode hyphens as word-boundries, so that title(SUNDSVALL–HÄRNASÖAND) => ”Sundsvall–Härnösand”
  • 8.10.1

    • [BUG] duration* should not use negative numbers
    • [BUG] duration* now handles 0
  • 8.10.0

    • [EXPERIMENTAL] Getter aliases for common methods. .territory* resolves to .territory*(region). This feature might go away in future releases if it has unwanted sideeffects. If it works, it will probably be moved to a NW-verse plugin.
  • 8.9.0

    • [NEW] denominator has a special value pretty, that may in the future be the default. It will prefer a predefined subset of fractions.
  • 8.8.0

    • [BREAKING] Requires NodeJS >=20 (up from 16!) From now on we will be on latest LTS Node versions, as we are no longer stuck with older environs in the robotwriters.
    • [BREAKING] Using list*() on an empty iterable will now throw an error, to reduce the risk of template errors.
    • [BREAKING] All duration*() methods now have non breaking spaces by default
    • [NEW] Added durationFromMinutes*().
    • [NEW] durationFrom() will now handle fractions, so that you can pass e.g. {hours: 2.3, minuter: 12}
    • [NEW] Added day*() for day of month only
    • [NEW] listDates(), listDayMonths(), listMonthYears() methods
    • [NEW] list*() now has a formatters option, taking formatters for list parts such like {default: day, start: dayMonth}, for advanced usecases where a simple .map() won't do.
    • [NEW] New argument type: dateList, used by listDate() etc. Can be any iterable, that will be converted to an array of date
    • [NEW] Added dayMonthPretty() for completeness
    • [BUG] Fixed unwanted zero padding in date formatting in some edge cases
  • 8.7.2

    • [DATA] Swedish compound form for Östra Göinge is now Göinge-
  • 8.7.1

    • [BUG] Fixed single digit time fragment parsing
  • 8.7.0

    • [NEW] approximateMultiplier() methods
    • [NEW] time input can now be hour fragments or integers, e.g. 19 (treated as "19:00")
  • 8.6.1

    • [BUG] Fix season bug affecting only(!) August 31
  • 8.6.0

    • [DATA] CLDR v.44, see https://cldr.unicode.org/index/downloads/cldr-44
    • [NEW] variant option to season()
    • [NEW] yearShort()
    • [NEW] turnOfYear() describes the closest year-end, e.g. “2012/13”
    • [NEW] seasonYear(). Note that tha default variant may be different from the season() default, e.g. in Swedish: “vinter”, but “vintern 2022/23”
    • Unified variants parsing
  • 8.5.1

    • [BUG] Fixed off-by-one bug in season()
  • 8.5.0

    • [NEW] Missing approximatelyText/Pretty() added
  • 8.4.0

    • [BREAKING] approximately() now works with small numbers and decimal places. This may break previous assumtions about smaller numbers always being untouched.
  • 8.3.1

    • [BUG] Fixed numberparsing to handle all zeroes as positive zeroes, like the docs say we should.
  • 8.3.0

    • [NEW] Added missing dateShort(), sinceShort(), sinceMonthShort()
  • 8.2.1

    • [BUG] .format() now works as it should with incomplete argument lists and gaps in placeholder enumeration.
  • 8.2.0

    • [NEW] smallestUnit options to duration*()
    • [NEW] durationText() and durationPretty()
    • [NEW] Duration methods for precalculated time spans: durationFromSeconds(), durationFromSecondsText(), durationFromSecondsPretty(), durationFrom(), durationFromText(), durationFromPretty()
  • 8.1.0

    • [BREAKING] *Pretty() methods will print any decimal numbers with digits
    • [NEW] Added missing millionsText(), billionsText(), millionsPretty(), and billionsPretty()
    • [NEW] Added approximateMillions*() and approximateBillions*()
    • [NEW] format() now works with output from other tF methods
    • [NEW] We now allow method specific, non-standard options
    • [NEW] multiplier*() for phrases like ”twice as ...”
    • [NEW] dayMonthText() for completeness. This means slightly different levels of spellout in different languages, eg ”tredje november” (sv), ”一月三日” (ja), ”January 3rd” (en), etc
    • [NEW] calendar option to date methods
    • [NEW] approximately() moved from Swedish plugin to core
    • [BUG] Respect options in date formatting in various date methods (for e.g. number formatting, calendar, ...)
    • [BUG] Fixed broken parameter parsing in season()
    • [BUG] Fixed pass-by-reference bug that could sometimes cause options to leak between method calls.
    • [DOC] From now on, we will not copy options documentation around between methods, unless their behaviour is non-default
  • 8.0.1

    • [BUG] Make Var vocab work in chains
  • 8.0.0

    • [NEW] EXPERIMENTAL support for Var-assigned vocab, to allow things like plural(Horses) => “hästar”
    • [NEW] optionsBeforeParse for plugins. Used by swedish-words to find gender, e.g numberText(Horses) => en”
  • 7.1.2

    • Revert to using require for loading local data, for better caching
  • 7.1.1

    • Swedish locative preposition för Lidingö changed from “i” to “på”
  • 7.1.0

    • [NEW] fractionParts() will return a diff value as a fourth slot
    • [NEW] quarternumber() for plain numerical quarter.
  • 7.0.5

    • [BUG] Fixed broken spellout of very small fractions in Swedish (tiotusendel)
  • 7.0.4

    • [DATA] Upstream fix to handle more complex RBNF patterns (for e.g. much improved Russian support).
    • Replaced nyc with c8 (using native V8 coverage, available since NodeJS 12) for test coverage reports.
  • 7.0.3

    • [BUG] Minor updates to cardinal variant parsing in bearing*(), making e.g. bearingPrimary(-30, {variant: "norr"}) (sv) work as intended (producing ”nordväst”)
    • Minor updates to date/time parsing
  • 7.0.2

    • [BUG] Make non-ascii latin characters work in territory codes
    • [DEV] Bundle Swedish plugin @ 2+
  • 7.0.1

    • [BUG] Fixed broken import of local data when used as ESM module
  • 7.0.0

    • [BREAKING] textFunction is now an ESM module! Use import textFunctions from "textFunctions" to import
    • [BUG] Fixed error in changeInteger decorators, causing argument parsing to fail
  • 6.9.0

    • [BREAKING] Do not allow undefined arguments to be passed in. This prevents misspelled variable names in Pug templates from going undetected. date() and date(CurrentDate) both works, but date(CurrentDtae) should now give an error.
    • [DATA] CLDR @ v43: https://cldr.unicode.org/index/downloads/cldr-43
  • 6.8.2

    • [BUG] Large ordinals are now formated: 1 234:e, etc.
    • [DATA] Added Swedish “landskap” (historical provinces), using codes from geneology journal Svenska Antavlor.
    • [DATA] Added landskap as a new territory type (se-4x, not in OSM)
    • Added more flexibility to territory type rules, by allowing regexes
  • 6.8.1

    • [BUG] Make Var type variables work in plural()
  • 6.8.0

    • [NEW] territoryType() and territoryTypeGeneric() added
  • 6.7.0

    • [NEW] upperFirst() will make the first letter upper-case, without touching any other letters (pre 6.6 behaviour of capital()).
  • 6.6.0

    • [BREAKING] capital() will make the tail lower-case, for consistency with Python's .capitalize(), our own .title(), and with virtually every other equivalent (and because that's the most common use case).
    • capital() no longer touches the first letter if it is already upper case. In some edge case lower().capital() and .capital() might now produce different results.
  • 6.5.0

    • [BREAKING] Optional date type arguments will default to today for consistency
    • [BREAKING] today now uses the user assigned timezone (default: UTC)
  • 6.4.0

    • [BREAKING] Un-registered options will be available to all methods, to make it easier to write plugins
    • [BREAKING] today and now are now tF objects to allow chaining, like now.addDays(12).month()
    • [DOC] now grouped with times
    • today is now a getter, like now for consistency, and to avoid caching issues.
    • Unified parsing of chained values
  • 6.3.1

    • [DOC] Fixed JSDoc syntax error
  • 6.3.0

    • [NEW] decameronMonth() and decameronMonthYear() for producing phrases like ”end of May”
  • 6.2.2

    • [BUG] argument parsers didn't have access to the tF object. Now they do, which should fix timeHM[S] errors in the swedish-words plugin.
  • 6.2.1

    • [DATA] Added some missing sv bearing() forms.
  • 6.2.0

    • [BREAKING] Second argument to bearing() is now required, to allow for unified options parsing.
    • [NEW] Added bearingCardinal(), bearingPrimary() and bearingSecondary().
    • [NEW] New option: variant. Similar to style, but allows any value and allows selecting by both value and key. Used in bearing*().
    • [BUG] Fixed overflow error in bearing() affecting negative numbers near north
  • 6.1.1

    • [DOC] Docdash upgraded. It's now easier to find options and properties in the docs
    • [BUG] precision works as expected when combined with decimal digits
    • precision parsing moved from options to _number, making unparsed number visible for methods. This allows approximately() from swedish-words plugin to function will custom precisions
  • 6.1.0

    • [NEW] bearing() converts degrees to compass courses (e.g. “northeast”)
    • [DATA] CLDR@v42, see https://cldr.unicode.org/index/downloads/cldr-42
  • 6.0.1

    • [BUG] add*() time methods now return UTC timestamps, as tF datetime strings cannot have timezone data (yet), and we want to avoid timezone errors in chaining.
  • 6.0.0

    • [BREAKING] tzOffset options can no longer be combined with timestamps with time offsets (e.g. 19:55:14.000+01:00), as this did not make much sense anyway. There should be very little need for the tzOffset option at all, now that time functions are timezone aware.
    • [BREAKING] Both timepoints are now required in duration (time2 no longer defaults to current time, as comparing to the time when a text was rendered made little sense, and this also made options parsing harder)
    • [NEW] duration() can now construct strings with number of days.
    • [NEW] duration() now takes options for e.g. number formatting.
    • [NEW] New option largestUnit used in duration(), to let template authors chose between “1 day and 2 hours”, and “26 hours”.
    • [NEW] textfunctions is now timezones-aware (we previously assumed UTC everywhere), and can be iniitiated with a timezone where texts are assumed to be consumed. We are using the new ES Temporal API, with a polyfill included.
    • [NEW] Time methods accept Temporal objects, as well as Date objects, and date/time-parsable strings.
    • [NEW] add*() methods for times, in analogy with addDays().
  • 5.10.2

    • [DATA] More grammar fixes for Swedish and Danish municipality names in Swedish and English.
  • 5.10.1

    • [DATA] Fixed some broken genitive forms for Swedish long form municipality names.
  • 5.10.0

    • [BREAKING] percent*(), change*() and sign() now use a new input parser, numberStrict, meaning that they will no longer accept iterables. This is to reduce errors due to bad data, as e.g. percentages of the length of an array doesn't make much sense anyway.
    • [NEW] list methods now have the glue option, to use custom binding words: list(["A", "B", "C"], {glue: "respektive"})
    • [NEW] dayMonthShort() added for consistency
    • [NEW] yearMonthsPretty() added for consistency
    • [NEW] changePercent() and changePercentInteger() added for consistency
    • [NEW] listOrUnique() and listUnique() will handle de-duplication in a uniform way. This can otherwise be tricky, as all variables passed around are complex objects.
    • [NEW] Variable types are now included in parser related error messages, so that the end-user can differentiate between [12] and 12.
  • 5.9.4

    • [BUG] Fixed rounding error in some edge cases with integerPretty() and related methods.
  • 5.9.3

    • [DATA] Correct locative compound form for minimalDistinct: Uppsala län
  • 5.9.2

    • [BUG] Fix off-by-one error in named (grouped) footnotes
  • 5.9.1

    • [BUG] Fix bug in named (grouped) footnotes, causing numbers to be displayed NaN
  • 5.9.0

    • [NEW] Support for named (grouped) footnotes (Wikipedia style).
    • [DATA] Fixed some broken genitive forms for long Swedish municipality names.
  • 5.8.0

    • [NEW] season() method describing primary seasons by location (e.g. “spring”)
    • [BREAKING] default beaviour of change() is now to write "±0". Note that this affects only change(), not sign().
    • [DEV] swedish-words at @1.7.5
  • 5.7.3

    • [BUG] Fixed side effects of subsequent use of list() with the level parameter
  • 5.7.2

    • [NEW] Added level option for use in e.g. nested lists (where a different separator might be preferred)
    • [BUG] Options are now passed on to helper functions used in formatting time durations, as it should be.
  • 5.7.1

    • [DATA] CLDR @ v41: https://cldr.unicode.org/index/downloads/cldr-41
    • [DEV] swedish-words included @1.7.4
  • 5.7.0

    • [BREAKING] largeNumber*(), millions() and billions() will now use non-breaking spaces
    • [DATA] Added some missing compound and locative forms for territoryDistinct() (sv)
  • 5.6.0

    • [NEW] added missing intervalDayMonth()
  • 5.5.0

    • [BREAKING] added two different .assign() methods: assign() and assignVar(), where only the second casts input to Var, reverting behavior of assign to that of
    • [BUG] Correct Swedish name for Norrtälje kommun
    • Add .slice() support to Var arrays
  • 5.4.0

    • [NEW] break option. Setting {break: "neverBreak"} will replace characters that usually break text in HTML with non-breaking variants (e.g. space -> non-breaking space). Useful for largeNumber(), etc
    • [BUG] Fix leaking options bug in chains
    • All methods now accept options argument(s). This gives plugins full freedom to accept extra options. Exception: t(), för backwards compatibility
    • Added post processing framework
  • 5.3.4

    • [BUG] Fixed integer parsing bug
  • 5.3.3

    • Various fixes for Array type Var() variables
  • 5.3.2

    • [BUG] Make list parsing with key option work when using assign()
  • 5.3.1

    • [BUG] Fix bug where first level null values caused assign to crash
    • Allow plugins to specify what languages they are allowed to work on.
  • 5.3.0

    • [NEW] Make .map() and .filter() methods available on Array type Var() variables. Things like List.map(x => x.name).list() are now possible, as well as List.map(x => x.name)[0].upper()
    • [BREAKING] Cast data to Var variables when using assign().
    • [BREAKING] Ignore numeric input to options, to allow all methods to be used in ES Array.map() calls. (In the future, all Var lists should have a custom map method instead.)
  • 5.2.0

    • Add argumentsBeforeParse hook, to support plugin swedish-words@1.5.0
    • Made territory a special input type, to centralise variable parsing, and allow plugins to add support to other territory keys.
  • 5.1.1

    • Fixed bug with hook calls when options are missing
  • 5.1.0

    • [NEW] Added resultAfterFunctionCall hook for modifying the output from built-in methods.
    • [NEW] Support swedish-words@1.4+ (with namedDay() and {style: 'article'})
  • 5.0.2

    • Added missing node dep.
  • 5.0.1

    • Fixed packaging issues in @newsworthy/swedish-words
  • 5.0.0

    • This major update adds plugin support, and moves existing Swedish dictionary functionality to a new plugin: @newsworthy/swedish-words, making textfunctions truly language-agnostic again, and also simplifying word list installation and maintenance a lot.
    • [NEW] Added argumentsBeforeFunctionCall hook, to allow plugins to modify function arguments
    • [BREAKING] Requires NodeJS >= 16.0
    • [BREAKING] Removed gender(), as out of scope for this project
    • [BREAKING] Moved form() to plugin @newsworthy/swedish-words
    • [BREAKING] Moved numberOf*() to plugin @newsworthy/swedish-words
    • [BREAKING] Moved dictionary support in plural() to plugin @newsworthy/swedish-words
    • [BREAKING] plural() with Swedish dictionary support will accept ambiguities, if the resulting output is non-ambigous, e.g. plural(2, "vind") (as both lemmas will have the same plural forms) {@newsworthy/swedish-words}
    • [BREAKING] plural() with Swedish dictionary support will now try to break up noun phrase compounds, making plural(2, "förortskommun") work {@newsworthy/swedish-words}
    • [BREAKING] form() with Swedish dictionary support will now try to break up noun phrase compounds {@newsworthy/swedish-words}
    • [BREAKING] numberOf*() with Swedish dictionary support will now try to break up noun phrase compounds {@newsworthy/swedish-words}
    • [BREAKING] All methods with Swedish dictionary support will now try to parse multi-word noun phrases, like "varuproducerande och besöksnäringskommuner" {@newsworthy/swedish-words}
    • [NEW] form() uses sg and pl for numerus (or alternatively cldr one/other). We will start using sg/pl in the dictionaries, as that's what Saldo uses at the source, but one/other will be kept as aliases for backwards compatibility. {@newsworthy/swedish-words}
    • [NEW] numberOf*() now follows the requested word's declinations, so that numberOf(x, "kommuns") => '15 kommuners' {@newsworthy/swedish-words}
    • [NEW] Return type can be toggled with returnVar option (defaults to true). If you ever want to use this lib outside templating engines (e.g. for chart production in the robotwriter), set this to false!
    • [NEW] list*() now has an extra decompound option when used with Swedish dictionary support, so that list(["skönhetsbranschen", "hälsobranschen"], "decompound") becomes 'skönhets- och hälsobranschen' {@newsworthy/swedish-words}
    • Refactored options system
  • 4.6.0

    • [DATA] Added extra Swedish territory data for nations
    • [EXPERIMENTAL] form() will now use its input to select a form, in case of ambiguity: form("kommuner", "def") => 'kommunerna'
  • 4.5.0

    • Add changeInteger()
  • 4.4.5

    • [DATA] Treat Gotland municipality and county as equal entities with regards to minimalDistinct name forms.
  • 4.4.4

    • [BUG] Fix gender errors in some methods (numberOfText, etc). These methods were not synced with the latest dictionary format.
  • 4.4.3

    • [BUG] Fix plural handling bug in largeNumber*()
    • [BUG] Another upstream fix for the new CLDR plural syntax (node-cldr is now at 7.0.0). French plurals should now be better behaved.
  • 4.4.2

    • [BUG] Fix #50, where precision would not have the right behaviour for small floats.
    • [BUG] Upstream fix for new plural syntax in CLDR 39, fixing issues with plurals in some languages.
  • 4.4.1

    • [BUG] Fix input parsing in largeNumberText and largeNumberPretty
    • [BUG] Enable missing precision in integer methods
  • 4.4.0

    • [BREAKING] Var variables now have the length property of their contained value
    • [BREAKING] largeNumber- methods will now only parse numbers above largeNumberLimit, a language specific limit.
    • [BREAKING] largeNumber- methods will now parse inputs as float (previously integer)!
    • [NEW] Precision option: number(9876, { precision: 1000 }) => ”10,000”
    • [NEW] largeNumberText no longer requires local grammar rules. While not always perfect, you will now have a reasonable default behaviour for most languages
    • [DATA] changed minimal distinct form for se-09 to “Gotland” (was “Gotlands län”)
    • Remove unused (and inconsistent) parsing logic from integer()
  • 4.3.0

    • [NEW] Add generative grammar rules for territories. These will allow automatic construction of some grammatical cases, making constructs like territory(xx, "locative") more useful.
    • [DATA] Update CLDR data to v.39, see: http://cldr.unicode.org/index/downloads/cldr-39
    • [BUG] Fix #46, where nesting date/time methods would sometimes not work.
  • 4.2.4

    • [BUG] Don't allow null values in method arguments
    • [BUG] Fix #41, where parsing of numeric arguments failed in nested method calls
  • 4.2.3

    • [BUG] percent*Text/Pretty() will now use the correct gender for percentages
  • 4.2.2

    • [DATA] Add missing short form for SE-1440
    • [DATA] Add territoryDistinct form for Swedish municipalities
    • [BUG] Make territoryDistinct fallback work for local data
  • 4.2.1

    • [BUG] Fix handling of nested function calls in plural()
  • 4.2.0

    • [NEW] Add percentIntegerText() and percentIntegerPretty()
    • [BUG] Var type variables now have access to all their value type's methods and properties, so that upper("Bass").replace("SS", "ß") works as one would expect.
  • 4.1.2

    • Make nested function calls work in template engines again, after being broken in 4.0.0
  • 4.1.1

    • Revert dictionary path test introduced in 4.0.0, as it failed on some file systems (Heroku)
  • 4.1.0

    • [BREAKING] Default denominator option is lowered 5, to avoid overly complex fractions.
    • [BREAKING] Avoid 0 as a numerator unless forced in fraction*() methods
    • [NEW] fractionText() takes a style options, for selecting special style forms. fractionText(0.5, "noun") will return 'hälften' in Swedish
    • [NEW] Added more grammatical cases, to be used in CLDR 39+ (adessive, allative, and many others).
    • [DATA] More grammatical forms added for Nordic municipalities in local territory database.
    • [BUG] Avoid crashing on very small fractions in fraction*() methods
  • 4.0.0

    • [NEW] Added a Var() factory method to create chainable variables: let a = Var(12); a.numberPretty().upper()
    • [NEW] Dictionaries can now contain homonyms. (All dictionary methods are still experimental!)
    • [BREAKING] All texts are now returned as a special object that allows chaining, removing the need for tampering with any global prototypes (this should make all features available in virtual sandboxes, and thus make it possible to expose the full library publicly through robotwriters like Murasaki). Returned variables have their toString() and valueOf() methods set to return the actual value. In a typical template engine, like Pug, variables are always cast to strings, meaning that the behavior should not change. However, it's likely that there will be some edge cases where e.g. chained methods now behave differently (e.g. raise an error in a different place in the chain.) See README
    • [BREAKING] If a grammatical case is missing, we will now fall back to nominative.
    • [BREAKING] All dictionary methods can now use any word form as their starting point (like plural() already did), allowing for easy access to homonymic lemmas. This affects case(), numberOf*(), gender(), and form()
    • [BREAKING] Dictionary methods will now throw an error on ambiguous input, like plural(n, "bok").
    • [BREAKING] Dictionaries are now required to use CLDR grammatical number classes (one, two, many, other, etc). This paves the way for dictionaries in any language, not just Swedish.
    • [BREAKING] plural() and numberOf() will immediately crash on words that do not have all numeral inflections available in the current language. A word like Swedish “kalsingar” is no longer allowed as the single argument to plural(). Use e.g. plural(underwear, "kalsipp", "kalsingar") instead.
    • [BREAKING] We will throw an error on setup if dictionary path is not found, closing #34
    • [DATA] Changed Swedish compound form for Södermanland from Södermanlands- to Sörmlands-
    • [DATA] Nordic municipalities added, as a local complement to the CLDR territories. These are fetched from WikiData, using national municipality codes (P1168 for Denmark, P1203 for Finland, P2504 for Norway, and P525 for Sweden) or local names (for Iceland and the Faroe Islands).
    • [DATA] Many Nordic municipalities and counties now have locative forms in Swedish, adding the right preposition (”i Stockholm, ”på Gotland”).
    • [DATA] Many Nordic municipalities and counties now have compund forms in Swedish: territory("se2080", { compound }) + "borna" => ”Faluborna”
    • [BUG] Fixed some validation issues in form()
    • [BUG] Chaining no longer pollutes global protoypes, closing #27 and partly #26.
    • [NEW/INTERNAL] Semi-public property _pluralClasses contains a list of all grammatical numbers in the current language (using CLDR names)
    • [DEPRECATION] Dictionaries should now use CLDR gender class names (neuter, reale, etc), to allow for dictionaries in any language. Support for the old names from the Swedish dictionary is deprecated and will be removed.
  • 3.4.1

    • [BUG] Use short fallback for territoryDistinct()
  • 3.4.0

    • [NEW] territoryDistinct() will display the shortest non ambiguous territory name.
  • 3.3.1

    • [BUG] Add missing data, to make quarterText() work. Forgot to check in a file in
  • 3.3.0

    • [NEW] quarter*(), quarterYear*() and relativeQuarter*() methods.
    • [NEW] Add relativeWeekdayText() and relativeWeekdayPretty(), for consistency.
    • Various doc fixes.
  • 3.2.1

    • [DATA] There is now a special compound “case” for some territories, for constructs like the Swedish ${ territoryShort("se-20", "compound") }flygplatserna => 'Dalaflygplatserna' (cmp. ${ territoryShort("se-20" ") } flygplatser => 'Dalarnas flygplatser')
    • [BUG] Fix broken test (test data was missing)
  • 3.2.0

    • [BREAKING] title() now treats dashes (-) as word boundaries.
    • [BREAKING] EXPERIMENTAL dictionary support in plural(). When given fewer words than there are plural classes in the language, we will now try and find the first word given in the dictionary, and fetch plural forms from there. This is obviously not fool-proof (there are homonyms with different declinations, for instance). Older dictionaries will no longer work!
  • 3.1.0

    • [NEW] Add percentInteger(), for completeness and consistency
    • [DATA] More grammar rules for largeNumber*
    • [BUG] Chaining now works the same way for any return type, as stated in the docs.
  • 3.0.1

    • [BUG] Make gender option work as intended for numberOf*(): numberOfText(1, "apelsin", "neuter") to have ”ett apelsin” (default ”en apelsin”)
    • Better dictionary cache error handling
    • Minor doc fixes
  • 3.0.0

    • [BREAKING] translations is now a regular options object (see README for a migration guide).
    • [BREAKING] Introducing ”naked” options: number(1, "neuter") for number(1, {gender: "neuter"}) and number(1, forceDecimalDigits) for number(1, {forceDecimalDigits}) / number(1, {forceDecimalDigits: true})
    • [BREAKING] Extra trailing arguments will be treated as options, making it possible to use multiple naked arguments, like numberPretty(x, "reale", "arab").
    • [BREAKING] Removed long deprecated method aliases fractionShort() (use fraction() instead) and _format() (use format() instead).
    • [BREAKING] Removed html debug markup in debug mode. This implementation was complex and buggy, and made some unsound assumptions about the end-implementation. Furthermore, markup is not really the scope of TF anyway. Markup debugging should be the job of a “robot writer”/template engine.
    • [BREAKING] Required Node >= 14.0, to allow using new V8 features (like optional chaining etc)
    • [NEW] Every standard method is now chainable. While chains like number(x).upper() might look nonsensical, they could be perfectly valid in some numbering systems (like Roman numerals!). Allowing chaining across the board makes the code easier to maintain, while removing unnecessary assumptions about languages.
    • [NEW] The case option has some shorthand aliases, like "gen" for "genitive"
    • [BUG] Fix an ugly bug that caused assigned context variables to sometimes leak from one method chain to another.
    • [BUG] Method chains no longer fails on empty string output (that can sometimes be a valid output!)
    • assign() no longer rejects key collisions in user data, when supplying multiple data objects
    • ICU feature detection was removed as Node versions without ICU are no longer supported anyway
    • .now no longer marked as experimental
  • 2.21.0

    • [NEW] case option for grammatical case in territory().
    • [NEW] territoryShort() for short variants (e.g. Hokkaido for Hokkaido prefecture). Limited coverage (this data is scraped from WikiData)
  • 2.20.0

    • [DATA] Update CLDR to release 38, see http://cldr.unicode.org/index/downloads/cldr-38
    • [NEW] ordinalAdverb() behavior has changed for consistency with other numerical methods. Use ordinalAdverb() for numerical output and ordinalAdverbText() for textual output. Deprecation warning and future$ordinalAdverb() method have been removed.
    • [NEW] Add relativeMonth* methods.
    • [NEW] Add relativeWeek* methods.
    • [NEW] Add relativeDay* methods.
    • [NEW]: Add relativeWeekday() method. Note that support for grammatical case is still very much WIP in CLDR, making this method somewhat limited in e.g. Finnish.
    • [NEW] Add weekNumber() for localised week numbers. Note that these can differ from ISO week numbers normally seen in computational contexts!
    • [NEW] .localeTerritory property will return the territory best matching the current locale; Either using explicitly stated locale tag, or using the default territories for the given language. This property is used internally to find the right week numbering algorithm.
    • Upstream fixes in node-cldr lib, to fix parsing errors in supplemental data.
    • Options parsing is a bit less strict, and options can now be casted to a different type.
  • 2.19.1

    • [BUG] Fix #23, a bug affecting time input.
  • 2.19.0

    • [NEW] relativeYear*() for phrases like ”last year”, ”this year”, etc.
    • [BUG] Fix rounding error bug in duration(), that in some edge cases could cause weird output like ”1 hour and 60 minutes”
    • Methods working on numbers will now use the size of a set or map, just like they already did with arrays and objects, for consistency.
    • Refactored argument parsing in preparation for a planned, bigger update. If you depend on parsing error messages, please note that some error messages shown on invalid input have changed.
  • 2.18.0

    • [BREAKING] Support for grammatical gender in dictionary data. Test implementation in numberOf*(). Older dictionaries will no longer work!
    • [NEW] gender() method to look up the gender of a dictionary word
    • Various error handling related to dictionaries and their methods.
  • 2.17.2

    • [BUG] Fix #22, where methods working on integers would parse input differently from other methods.
    • [TEST] Use strict comparisons for all method tests.
  • 2.17.1

    • [DATA] Update CLDR to release 37, see http://cldr.unicode.org/index/downloads/cldr-37
    • [DATA] Added a local override for Swedish, making “Belarus” replace “Vitryssland” for 'by', as this is now the preferred term among Swedish news media in both Sweden and Finland.
    • [BUG] Fix #20, and some related issues with decimal numbers in numberOf*()
    • [DOC] Fix duplicated options in docs.
  • 2.17.0

    • [BREAKING] Integer input will now be rounded, if given as a float. This affects a number of methods, e.g. ordinal*()
    • [NEW] Experimental form() method to find a declination of a word
    • [NEW] Experimental numberOf*() methods
    • [NEW] New numbering system diak, for old Maldivian Dhives Akuru numbers, added with Unicode 13.
    • [BUG] Fixes a bug in duration() where “1 minute and 0 seconds” was sometimes printed out, rather than “1 minute”.
    • [BUG] Upstream fix for a bug where ordinal*() methods used Latin digits even for scripts with non-latin defaults.
    • duration() and time*() methods no longer marked as experimental
    • Cldr updated to 63.1, for e.g. Unicode 13
  • 2.16.2

    • All time methods now parse timezone input correctly, and defaults to UTC, to make sure all servers handle ambiguous timestamps the same way.
    • add tzOffset option, for setting a time zone (in minutes). new Date().getTimezoneOffset() will give you the current local offset.
  • 2.16.1

    • now now contains the current timestamp (as the name would imply).
  • 2.16.0

    • [BREAKING] We now require NodeJS >= 13.0
    • [NEW] Official recommendation: Use PascalCase or UPPER_CASE for data variables when sharing namespace with textFunctions methods, as textFunctions promises to only ever use lowerCamelCase for methods, properties and constants.
    • [NEW] Experimental date/time methods and properties added: now, duration(), timeHMS(), timeHM() and timeH(). Everything about those may change, including their names!
    • [NEW] Added style option to show how e.g. a month name is intended to be used: standAlone or format (the latter for constructing e.g. a date string).
    • [BUG] Fixed a month name bug affecting Finnish, Catalan and possibly others, where the wrong month name style was used in full dates.
  • 2.15.1

    • capital() now works for non-BMP characters, such as '𐑀'. Great news for anyone using Medieval Hungarian, for instance. :)
    • Fixed a bug where capital() and title() crashed on empty input.
  • 2.15.0

    • Added methods future$ordinalAdverb(), ordinalAdverbText() and ordinalAdverbPretty()
    • Marked ordinalAdverb() as deprecated; to be replaced by future$ordinalAdverb() at some point
    • A number of bug fixes in deprecated ordinalAdverb.
  • 2.14.2

    • Upstreams bug fix, that addresses several bugs with decimal digits in *Text methods. See https://github.com/papandreou/node-cldr/issues/102
  • 2.14.1

    • Fix documentation for optionDefaults property.
  • 2.14.0

    • Allow overriding defaults through the textfunctions.optionDefaults object. Setting optionDefaults.decimalDigits = 4 will make four decimal digits the default for all numeric methods.
    • *Text methods will now round, not truncate numbers, as one would expect, and in line with other methods.
  • 2.13.2

    • Make *Pretty-methods work for negative numbers.
    • Date-interval methods now use absolute numbers, because “minus eight years” doesn't make much sense.
    • Minor documentation fixes
  • 2.13.1

    • Upgrade Cldr dependency with bug fix for packaging issue, causing installation to fail in some environments.
    • Add narrow non breaking space (nnbsp) support to char().
    • plural() now works on sets and maps, just like it already did on arrays och objects: let s = new Set(["a", "b"]); plural(s, "one", "many") will return 'many'
    • Unified handling of positive/negative zeroes (yes, JavaScript has both...) in methods taking numerical input. This should have no visible side-effects on current methods.
    • Minor documentation fixes
  • 2.13.0

    • Add fuzzyDate() method, for partial date strings, e.g. 2018-03 (March 2018).
    • year() takes number formatting options, so that year("2017-12-31", {numberSystem: "roman"}) returns 'MMXVII' (English), 'MMXVII年' (Japanese), etc.
    • Documentation fixes
  • 2.12.0

    • CLDR 36, see http://cldr.unicode.org/index/downloads/cldr-36
    • fix documentation errors for largeNumber*()
    • Enable decimal digits in largeNumber*() for consistency
  • 2.11.0

    • added largeNumberText() and largeNumberPretty()
  • 2.10.5

    • Upgrade node-cldr to 5.4.1, to fix packaging error
  • 2.10.4

    • Re-release to clean up node_modules
  • 2.10.3

    • Fix issue #13: plural() now uses the decimalDigits option, to be consistent with surrounding methods. let val = 1.0002; ${number(val)} pink ${plural(val, "dolphin", "dolphins")} will now return “1 pink dolphin”, not “1 pink dolphins”
    • Upgrade node-cldr to 5.4.0, for fewer dependencies
  • 2.10.2

    • Remove CLDR notes from territory names (e.g. fridf, Île-de-France)
  • 2.10.1

    • territory("RS-00") is now "Belgrade", not "Beograd" in English, using a local override
  • 2.10.0

    • Add char() method
  • 2.9.1

    • Add GR-A1 as supplemental territory code for GR-I
  • 2.9.0

    • [BREAKING] Fixed a leap year bug in some interval methods. months("2004-01-31", "2004-02-28") will now correctly return '0 months', whereas months("2003-01-31", "2003-02-28") returns '1 month', as we count only full months passed.
    • [BREAKING] Make sign() behave the same as every other method with regards to positive and negative 0 (they are now all treated like 0).
    • territory() now looks for deprecated or alternative territory codes listed in CLDR, before falling back to local last-resort, increasing the number of valid codes by 784. In some cases a deprecated code can map to multiple new. These will be passed through list(), so that territory(AN) => 'Curaçao, Sint Maarten och Karibiska Nederländerna' (sv).
    • territory() now removes disambiguity appendixes, like the ' (province)' in "Liège (province)". Note that this will not affect e.g. "Myanmar (Burma)", where the paranthesis serve a different purpose.
    • Fix issue #12: Algorithmic number systems fail for negative numbers in numberText()
    • Fix issue with whole numbers in fractionText(), where the correct default gender was not applied
    • Hard-code Latin digits in change() for improved performance
    • Improved performance for territory()
    • Various stability improvements in number formatting module
    • Added list sample strings to options.html#numberSystem documentation
    • Improved test coverage
  • 2.8.1

    • Added local fallback rules in territory() for common or deprecated ISO codes that CLDR does not understand. territory("czst"), the code used for Středočeský in the Czech Republic until late 2018, will now work as an alias for territory("cz20"), and territory("SE-05"), an alternative designation for Östergötland, will work as an alias for territory("SE-E").
  • 2.8.0

    • territory() now supports all sub-national divisions in CLDR: territory("SE-ac") => “Västerbottens län”
    • [BREAKING] territory() will now produce an error on missing or invalid locales, rather than crashing.
    • [BREAKING] *Pretty()-methods will now use numerical output if there is a fractional part in the final output.
  • 2.7.4

    • CLDR updated to version 35, with local names for “North Macedonia”, improved support for Somali and Javanese, and much, much more: http://cldr.unicode.org/index/downloads/cldr-35
  • 2.7.3

    • Upstream bug-fix in node-cldr (5.0.2), to make some number systems with digits with high Unicode code-points work (e.g. the previously broken number(123.3, {numberSystem: "ahom"})
    • Upstream bug-fix in node-cldr (5.0.3), to solve issue with numberText() for high number. Test case: numberText(1800000)
    • Improved number formatting module, to make more number systems and number formats work as expected
  • 2.7.2

    • make largeNumber(), millions(), and billions() chainable
    • fix a bug in superScript() and subScript() that would make them fail for strings with high code-points Unicode characters.
  • 2.7.1

    • largeNumber() takes a magnitude option to force a certain unit. millions(val) is equal to largeNumber(val, {magnitude: 6}).
    • Add billions() as an alias for largeNumber(val, {magnitude: 9})
  • 2.7.0

  • Added largeNumber() and millions() methods

  • 2.6.0

    • [BREAKING] change() will now round all numbers, rather than truncating, following roughly the same internal logic as number*()
    • Make debugData() work properly in debug mode (doh!)
    • Make fractionShort() output deprecation warning in debug mode (should have been done in 2.4.0)
    • Updated the JSDoc skin (DocDash) to remove jQuery dependency.
  • 2.5.1

    • Update in CLDR dependency fixes some RBNF rule parsing errors.
    • Make numberText() work for negative numbers.
    • Make numberPretty() use number() as a fallback rather than crashing on missing CLDR data
  • 2.5.0

    • [BREAKING] number*() will now round, rather than truncate numbers. This was always ambigous in the docs.
    • Added English rules for fractionText()
    • Added debugData() method for printing out debugging data in the robot writer
  • 2.4.0

    • Make fraction() use sub scripted and super scripted numbers, when available, because very few fonts fully support the Unicode fraction sign.
    • Make fraction() use narrow non-breaking space between whole part and fraction, in the default layout (usually 3/4 of a normal space).
    • Deprecate fractionShort() again, as it is now typographically very similar to fraction(); the compound characters are not recommended by Unicode; and the method name was in-consistent with the rest of the lib anyway (*Short names are otherwise used for abbreviations and the like).
    • Add superScript() and subScript(). These are now used internally when composing fractions, but could also be useful when working with e.g. Mathematics or Chemistry: C${subScript(carbon)}H${subScript(oxygen)}OH => C₂H₅OH
    • Improved fractionText() support for Swedish
    • Documentation fixes
  • 2.3.0

    • Make sure failing method name is always included in error message (an issue with how internal function calls works caused it to miss out in some cases)
    • Added methods fraction(), fractionShort() and fractionText(), with limited language support. Will print things like ¼, one third, 1 1⁄2, and . Note that language specific gender and plural rules may require much more sophisticated logic than can be provided here. This is often best defined on a per-template bases (see utility methods below).
    • Added utility method fractionParts(), primarily for use in template level functions
    • Expose previously internal, undocumented formatting method as format(), primarily for use in template level function. Example: format("The {0} on the bus go {1} and {1}", "wheels", "round"). fractionParts and format could be used together to describe a statistical probability: let shareOf = x => format("{0} out of {1}", fractionParts(x, {denominator: 10}).slice(1).map(y => numberText(y))); shareOf(0.3333) => 'one out of three'.
    • Deprecate _format()
    • Use defaults for covering up partially supported languages in local (non CLDR) language data. Methods relying on local language data will now give reasonable output in more languages.
  • 2.2.0

    • Make previously private, undocumented abs() method public.
    • Add percentText() and percentPretty()
    • *Text() methods will now use the decimalDigits options, so that numberText(3.141592, {decimalDigits: 2}) => 'Tre komma fjorton' This should make percentPretty more useful.
    • Make *Text() methods throw an error on negative input, rather than failing silently.
    • Various documentation fixes.
  • 2.1.1

    • Fix version number in package.json
  • 2.1.0

    • Enable boolean shortcuts in options. number(2.0, {forceDecimalDigits: true}) can now be written as number(2.0, {forceDecimalDigits})
    • Better grouping of methods in docs
    • Speed up number() for Latin numbers, by hard coding digits
  • 2.0.1

    • Various dependency updates, notably node-cldr@5.0.0
  • 2.0.0

    • [REQUIREMENT] From this version we require NodeJS >= 10.0.0, jumping up from 6.0.0
    • [BREAKING] The lang property will now contain the whole fallback chain of language tags (but not languages that are automatically deduced)
    • [BREAKING] lang is now read-only. Making it writable added complexity with little extra advantages. If you need to switch languages while in the middle of rendering, you should use two separate textfunctions instances, as was always the recommendation.
    • [BREAKING] ordinalAdverb(), years*(), yearMonths*(), months*(), and t*() will now check for both the specific locale, and the more general tags, e.g. de-AT => de, before moving on to the next language in the fallback chain. This is the logic that all other methods were already following. Specifying language tags of different detail level is no longer useful, or meaningful. ["sv-AX", "sv"] is the same as "sv-AX". Note that specifying a macro language as a fallback could still be useful: ["nn", "no"]. Try being as specific as possible in language tags.
    • Methods that take numerical input will now accept arrays and objects, and use their length as the value. This often makes sense semantically in a templating environment, where you can now write things like There #{plural(new_parties, "is", "are")} #{number(new_parties)} new #{plural(new_parties, "party", "parties")} in the parliament: #{list(new_parties)} (Pug syntax).
    • Added a numberSystem option for methods with numerical output, e.g. number(x, {numberSystem: 'latn'}) to force using Latin number in an Arabic text.
    • You can now keep multiple parallel footnote systems going, by specifying different number systems, e.g. using roman numerals for footnotes in a table, inside a longer article with footnotes using Latin numerals.
    • percent() and integerPretty() got lost in the documentation in 1.11.0, they are back now
    • Unified cache handling for easier maintenance and more consistent behavior across methods
    • Make year() use proper date formatting, most notably affecting East Asian languages
    • Fix bug in number formatting for patterns with repeated group markers, e.g. Indian number formats
    • Removed "number-format.js" dependency
    • Error handling fixes
  • 1.12.3

    • Further cleanup of debug output
  • 1.12.2

    • Fix versioning error (1.12.0 was accidentally released as 1.12.1)
  • 1.12.0

    • Add disjunctive lists with listOr() (A, B, or C) and tListOr()
    • Various improvements in debug output
  • 1.11.1

    • Fix linting errors
  • 1.11.0

    • Fix bug in options to numberPretty()
    • Remove deprecated percentPretty() (that did not work well across languages)
    • Remove deprecated percentWithSign()
    • Re-introduce percent(), as an alias for number(x - 100)
    • Group documentation thematically
  • 1.10.0

    • [BREAKING] Non-allowed values in options will now return an error, rather than falling back to the default. Invalid test case: numberText(1, {gender: "dog"})
    • Added addDays(), addMonths(), and addYears() methods to add or subtract days, months, years.
    • Chaining no longer considered experimental. Now documented, and fairly well covered by tests.
    • Better date formatting coverage
    • Added missing test cases
  • 1.9.5

    • Refactor out all Intl dependencies, to use CLDR data directly
  • 1.9.4

    • Remove old code that added stuff to the String prototype.
    • Improved argument parsing and error messages for list arguments (affects list() and tList())
    • Changes to Intl loading, to try mitigating a bug in some date functions
  • 1.9.3

    • Make chaining work with multiple arguments. This also allows passing options to intermediate steps: random(1, 2, 3).numberText({gender: "reale"}).upper()
    • Extended chaining support
    • Print out deprecation warnings for deprecated methods in debug mode.
    • Documentation fixes
  • 1.9.2

    • Re-release with correct version number in package.json
  • 1.9.1

    • Make debug mode work with chained methods
    • Throw error on invalid number inputs, that would previously be rendered as NaN
    • Add fn() as an alias for footnote()
    • Make debug show unparsed arguments
  • 1.9.0

    • Fix bug in list(), where empty lists returned nonsense.
    • Improved debug coverage
    • Make internal lang() method a property, and expose it
    • Allow changing language/locale by setting a lang property
    • Add missing integerText(), for completeness
    • Unify argument parsing, making sure that all input is treated equally
    • Always throw errors on invalid input
    • Dates may now only be given as strings or date objects. This is what the docs always said, but in reality you could use whatever the Javascript Date() constructor would swallow.
    • Experimental, partial support for chaining: month().upper(), as an alternative to upper(month()), or random(1, 2, 3).numberText().upper(), as an alternative to upper(numberText(random(1, 2, 3)))
    • random() will now always return text.
  • 1.8.1

    • Make references() work in debug mode.
    • Clean up debug mode output
  • 1.8.0

    • Throw an error on missing input to plural()
    • Remove deprecated percentText method that was not used by any templates
    • ordinalAjective() use numerals for large numbers, e.g. "222:a största" or "222.größte"
    • Improved number formatting in number(), that no longer relies on Intl.NumberFormatting. forceDecimalDigits and other options should now work as expected.
    • Added a debug mode with stricter warnings, and additional html mark-up
  • 1.7.1

    • Fix a bug where change() would show an unwanted sign for small floats
  • 1.7.0

    • Add key options to tList()
    • Put conjugation in the options object to t() and tList(), but with backwards compatibility for t()
  • 1.6.1

    • Fixed a bug in yearMonth*(), where dates passed by reference were altered
  • 1.6.0

    • Added months*(), years*(), and yearMonths*() methods for a few languages.
    • Make ordinalAdverb() less specific when looking for rules. Both de-DE and de-AT will now return the same German rule set.
  • 1.5.2

    • Increased test coverage
    • Documentation updates
  • 1.5.1

    • Fix JSDoc bug
  • 1.5.0

    • Change the call sign from references to references(), to make it work in some edge cases
    • Fix an ugly caching bug in plural()/pl()
    • Added PugJS tests
  • 1.4.1

    • Cache unit patterns
  • 1.4.0

    • Add assign() semi-private method (not for template authors)
  • 1.3.0

    • Add footnote() and references
    • Add since* methods
    • Add interval* methods
    • Add integer* methods
    • Add weekday* methods
    • Remove some unused code
    • Some documentation fixes
  • 1.2.0

    • Fix bug where today did not contain the date
    • Make all public methods return an error message on internal exceptions. The rationale is that text function errors are of more interest to template authors, than to the server processing them.
    • Report an error on invalid month numbers
  • 1.1.2

    • Changed the way options are parsed under the hood
    • Improved jsdoc structure
  • 1.1.1

    • Only load Intl module when needed
    • Cache list patterns, RNBF functions and plural rules
    • Better test coverage
  • 1.1.0

    • title() for title case
  • 1.0.0

    • First version, migrated from J++