{"version":3,"file":"index.mjs","names":[],"sources":["../index.ts"],"sourcesContent":["// TYPES: PARSING\nexport type TimeSignatureLiteral = string | [number, number] | [string, string];\ntype ParsedTimeSignature = [number | number[], number];\n\n// TYPES: PROPERTIES\nexport type ValidTimeSignature = {\n  readonly empty: false;\n  readonly name: string;\n  readonly upper: number | number[];\n  readonly lower: number;\n  readonly type: \"simple\" | \"compound\" | \"irregular\" | \"irrational\";\n  readonly additive: number[];\n};\n\nexport type InvalidTimeSignature = {\n  readonly empty: true;\n  readonly name: \"\";\n  readonly upper: undefined;\n  readonly lower: undefined;\n  readonly type: undefined;\n  readonly additive: [];\n};\n\nexport type TimeSignature = ValidTimeSignature | InvalidTimeSignature;\n\n// CONSTANTS\nconst NONE: InvalidTimeSignature = {\n  empty: true,\n  name: \"\",\n  upper: undefined,\n  lower: undefined,\n  type: undefined,\n  additive: [],\n};\n\nconst NAMES = [\"4/4\", \"3/4\", \"2/4\", \"2/2\", \"12/8\", \"9/8\", \"6/8\", \"3/8\"];\n\n// PUBLIC API\n\nexport function names() {\n  return NAMES.slice();\n}\n\nconst REGEX = /^(\\d*\\d(?:\\+\\d)*)\\/(\\d+)$/;\n// Common time and cut time symbols\nconst ALIASES = new Map([\n  [\"C\", \"4/4\"],\n  [\"c\", \"4/4\"],\n  [\"C|\", \"2/2\"],\n  [\"¢\", \"2/2\"],\n]);\nconst CACHE = new Map<TimeSignatureLiteral, TimeSignature>();\n\nexport function get(literal: TimeSignatureLiteral): TimeSignature {\n  const stringifiedLiteral = JSON.stringify(literal);\n  const cached = CACHE.get(stringifiedLiteral);\n  if (cached) {\n    return cached;\n  }\n\n  const ts = build(parse(literal));\n  // Only valid signatures are cached, so arbitrary input can't grow the cache\n  if (!ts.empty) CACHE.set(stringifiedLiteral, ts);\n  return ts;\n}\n\nexport function parse(literal: TimeSignatureLiteral): ParsedTimeSignature {\n  if (typeof literal === \"string\") {\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    const [_, up, low] = REGEX.exec(ALIASES.get(literal) ?? literal) || [];\n    return parse([up, low]);\n  }\n\n  const [up, down] = literal;\n  const denominator = +down;\n  if (typeof up === \"number\") {\n    return [up, denominator];\n  }\n\n  // Guard against input that does not match REGEX (e.g. \"C\"): the exec above\n  // yields an undefined `up`, so `up.split` would throw. Return a zeroed parse\n  // that `build` maps to the NONE signature, matching invalid inputs like \"0/0\".\n  if (typeof up !== \"string\") {\n    return [0, 0];\n  }\n\n  const list = up.split(\"+\").map((n) => +n);\n  return list.length === 1 ? [list[0], denominator] : [list, denominator];\n}\n\n/** @deprecated */\nexport default { names, parse, get };\n\n// PRIVATE\n\nconst isPowerOfTwo = (x: number) => (Math.log(x) / Math.log(2)) % 1 === 0;\n\nfunction build([up, down]: ParsedTimeSignature): TimeSignature {\n  const upper = Array.isArray(up) ? up.reduce((a, b) => a + b, 0) : up;\n  const lower = down;\n  if (upper === 0 || lower === 0) {\n    return NONE;\n  }\n\n  const name = Array.isArray(up) ? `${up.join(\"+\")}/${down}` : `${up}/${down}`;\n  const additive = Array.isArray(up) ? up : [];\n  const type =\n    lower === 4 || lower === 2\n      ? \"simple\"\n      : lower === 8 && upper % 3 === 0\n        ? \"compound\"\n        : isPowerOfTwo(lower)\n          ? \"irregular\"\n          : \"irrational\";\n\n  return {\n    empty: false,\n    name,\n    type,\n    upper,\n    lower,\n    additive,\n  };\n}\n"],"mappings":";AA0BA,MAAM,OAA6B;CACjC,OAAO;CACP,MAAM;CACN,OAAO,KAAA;CACP,OAAO,KAAA;CACP,MAAM,KAAA;CACN,UAAU,CAAC;AACb;AAEA,MAAM,QAAQ;CAAC;CAAO;CAAO;CAAO;CAAO;CAAQ;CAAO;CAAO;AAAK;AAItE,SAAgB,QAAQ;CACtB,OAAO,MAAM,MAAM;AACrB;AAEA,MAAM,QAAQ;AAEd,MAAM,0BAAU,IAAI,IAAI;CACtB,CAAC,KAAK,KAAK;CACX,CAAC,KAAK,KAAK;CACX,CAAC,MAAM,KAAK;CACZ,CAAC,KAAK,KAAK;AACb,CAAC;AACD,MAAM,wBAAQ,IAAI,IAAyC;AAE3D,SAAgB,IAAI,SAA8C;CAChE,MAAM,qBAAqB,KAAK,UAAU,OAAO;CACjD,MAAM,SAAS,MAAM,IAAI,kBAAkB;CAC3C,IAAI,QACF,OAAO;CAGT,MAAM,KAAK,MAAM,MAAM,OAAO,CAAC;CAE/B,IAAI,CAAC,GAAG,OAAO,MAAM,IAAI,oBAAoB,EAAE;CAC/C,OAAO;AACT;AAEA,SAAgB,MAAM,SAAoD;CACxE,IAAI,OAAO,YAAY,UAAU;EAE/B,MAAM,CAAC,GAAG,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,KAAK,OAAO,KAAK,CAAC;EACrE,OAAO,MAAM,CAAC,IAAI,GAAG,CAAC;CACxB;CAEA,MAAM,CAAC,IAAI,QAAQ;CACnB,MAAM,cAAc,CAAC;CACrB,IAAI,OAAO,OAAO,UAChB,OAAO,CAAC,IAAI,WAAW;CAMzB,IAAI,OAAO,OAAO,UAChB,OAAO,CAAC,GAAG,CAAC;CAGd,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;CACxC,OAAO,KAAK,WAAW,IAAI,CAAC,KAAK,IAAI,WAAW,IAAI,CAAC,MAAM,WAAW;AACxE;;AAGA,IAAA,yBAAe;CAAE;CAAO;CAAO;AAAI;AAInC,MAAM,gBAAgB,MAAe,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAK,MAAM;AAExE,SAAS,MAAM,CAAC,IAAI,OAA2C;CAC7D,MAAM,QAAQ,MAAM,QAAQ,EAAE,IAAI,GAAG,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI;CAClE,MAAM,QAAQ;CACd,IAAI,UAAU,KAAK,UAAU,GAC3B,OAAO;CAGT,MAAM,OAAO,MAAM,QAAQ,EAAE,IAAI,GAAG,GAAG,KAAK,GAAG,EAAE,GAAG,SAAS,GAAG,GAAG,GAAG;CACtE,MAAM,WAAW,MAAM,QAAQ,EAAE,IAAI,KAAK,CAAC;CAU3C,OAAO;EACL,OAAO;EACP;EACA,MAXA,UAAU,KAAK,UAAU,IACrB,WACA,UAAU,KAAK,QAAQ,MAAM,IAC3B,aACA,aAAa,KAAK,IAChB,cACA;EAMR;EACA;EACA;CACF;AACF"}