Example

Common Values

Everyday structured values.

A compact library of common values: numbers, money, dates and times, IP addresses, email addresses, URLs, UUIDs, and semantic versions.

What it shows

  • Number has Decimal and Integer forms; decimal values do not match parts of times or IPv4 addresses.
  • Money, Percentage, Date, Time, Timestamp, and Duration expose their useful parts as fields.
  • EmailAddress exposes localPart and domain; Url exposes scheme, domain, path, query parameters, and fragment.
  • IPv4Address, Uuid, and SemanticVersion expose their standard components.
  • Currency maps codes and symbols to stable identities.

Try adding another currency or URL scheme.

Specs

spec.yml
$flags: ['FLEXIBLE_WHITESPACE', 'WORD_BOUNDARY']

IPv4Address:
  $types:
    Octet: '25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d'
  $fields:
    first: Octet
    second: Octet
    third: Octet
    fourth: Octet
  $patterns: '#{first}\.#{second}\.#{third}\.#{fourth}'

EmailAddress:
  $types:
    LocalPart: '[A-Za-z0-9._%+-]+'
    DomainLabel: '[A-Za-z0-9-]+'
    TopLevelDomain: '[A-Za-z]{2,}'
    HostName: '${DomainLabel}(\.${DomainLabel})*\.${TopLevelDomain}'
  $fields:
    localPart: LocalPart
    domain: HostName
  $patterns: '#{localPart}@#{domain}'

Url:
  $types:
    Scheme: 'https?'
    DomainLabel: '[A-Za-z0-9-]+'
    TopLevelDomain: '[A-Za-z]{2,}'
    HostName: '${DomainLabel}(\.${DomainLabel})*\.${TopLevelDomain}'
    Path: '/[^\s?#]*'
    Query:
      $types:
        ParameterName: '[^\s=&#]+'
        ParameterValue: '[^\s&#]+'
        Parameter:
          $fields:
            name: ParameterName
            value: ParameterValue
          $patterns: '#{name}(=#{value})?'
      $fields:
        parameters: 'Parameter[]'
      $patterns: '#{parameters}(&#{parameters})*'
    Fragment: '[^\s#]+'
  $fields:
    scheme: Scheme
    domain: HostName
    path: Path
    query: Query
    fragment: Fragment
  $patterns: '#{scheme}://#{domain}#{path}?(\?#{query})?(\##{fragment})?'

Uuid:
  $types:
    HexDigit: '[0-9A-Fa-f]'
    HexGroup: '${HexDigit}+'
  $fields:
    timeLow: { $type: HexGroup, $match: '${HexDigit}{8}' }
    timeMid: { $type: HexGroup, $match: '${HexDigit}{4}' }
    timeHighAndVersion: { $type: HexGroup, $match: '${HexDigit}{4}' }
    clockSequence: { $type: HexGroup, $match: '${HexDigit}{4}' }
    node: { $type: HexGroup, $match: '${HexDigit}{12}' }
  $patterns: '#{timeLow}-#{timeMid}-#{timeHighAndVersion}-#{clockSequence}-#{node}'

Number:
  $flags: '-WORD_BOUNDARY'
  Decimal: '(?<![:.\d])\d+(,\d{3})*\.\d+(?![:.\d])'
  Integer: '\d+(,\d{3})*'

Percentage:
  $fields:
    value: Number
  $patterns: '#{value}%'

Currency:
  US_Dollar: [ 'USD', '\$' ]
  Euro: [ 'EUR', '€' ]
  BritishPound: [ 'GBP', '£' ]

Money:
  $flags: 'OPTIONAL_WHITESPACE'
  $fields:
    currency: Currency
    amount: Number
  $patterns:
    - '#{currency} #{amount}'
    - '#{amount} #{currency}'

SemanticVersion:
  $types:
    PreReleaseIdentifier: '([A-Za-z-]|${Number::Integer})+'
    PreRelease: '${PreReleaseIdentifier}(\.${PreReleaseIdentifier})*'
  $fields:
    major: Number::Integer
    minor: Number::Integer
    patch: Number::Integer
    preRelease: PreRelease
  $patterns: 'v?#{major}\.#{minor}\.#{patch}(-#{preRelease})?'

Date:
  $flags: '-WORD_BOUNDARY'
  $fields:
    year: { $type: Number::Integer, $match: '\d{4}' }
    month: { $type: Number::Integer, $match: '0[1-9]|1[0-2]' }
    day: { $type: Number::Integer, $match: '0[1-9]|[12]\d|3[01]' }
  $patterns:
    - '#{year}-#{month}-#{day}'
    - '#{month}/#{day}/#{year}'
    - '#{day}-#{month}-#{year}'

Time:
  $flags: '-WORD_BOUNDARY'
  $fields:
    hour: { $type: Number::Integer, $match: '[01]\d|2[0-3]' }
    minute: { $type: Number::Integer, $match: '[0-5]\d' }
    second: { $type: Number::Integer, $match: '[0-5]\d' }
    milliseconds: { $type: Number::Integer, $match: '\d{3}' }
  $patterns: '#{hour}:#{minute}:#{second}(\.#{milliseconds})?'

UtcOffset:
  $types:
    OffsetSign: '[+-]'
  $fields:
    sign: OffsetSign
    hour: { $type: Number::Integer, $match: '[01]\d|2[0-3]' }
    minute: { $type: Number::Integer, $match: '[0-5]\d' }
  $patterns: '#{sign}#{hour}:#{minute}'

Timestamp:
  $fields:
    date: Date
    time: Time
    offset: UtcOffset
  $patterns: '#{date}T#{time}#{offset}?'

Duration:
  $flags: 'OPTIONAL_WHITESPACE'
  $fields:
    value: Number
  Hours: '#{value} (h|hours)'
  Minutes: '#{value} (m|minutes)'
  Seconds: '#{value} (s|seconds)'
  Milliseconds: '#{value} (ms|milliseconds)'
Try it liveOpen Common Values in StudioTweak the spec, paste your own input, and see the parse tree update in real time.

Or browse other examples →