decode-owl.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import { assertArgument } from "../utils/index.js";
  2. const subsChrs = " !#$%&'()*+,-./<=>?@[]^_`{|}~";
  3. const Word = /^[a-z]*$/i;
  4. function unfold(words: Array<string>, sep: string): Array<string> {
  5. let initial = 97;
  6. return words.reduce((accum, word) => {
  7. if (word === sep) {
  8. initial++;
  9. } else if (word.match(Word)) {
  10. accum.push(String.fromCharCode(initial) + word);
  11. } else {
  12. initial = 97;
  13. accum.push(word);
  14. }
  15. return accum;
  16. }, <Array<string>>[]);
  17. }
  18. /**
  19. * @_ignore
  20. */
  21. export function decode(data: string, subs: string): Array<string> {
  22. // Replace all the substitutions with their expanded form
  23. for (let i = subsChrs.length - 1; i >= 0; i--) {
  24. data = data.split(subsChrs[i]).join(subs.substring(2 * i, 2 * i + 2));
  25. }
  26. // Get all tle clumps; each suffix, first-increment and second-increment
  27. const clumps: Array<string> = [ ];
  28. const leftover = data.replace(/(:|([0-9])|([A-Z][a-z]*))/g, (all, item, semi, word) => {
  29. if (semi) {
  30. for (let i = parseInt(semi); i >= 0; i--) { clumps.push(";"); }
  31. } else {
  32. clumps.push(item.toLowerCase());
  33. }
  34. return "";
  35. });
  36. /* c8 ignore start */
  37. if (leftover) { throw new Error(`leftovers: ${ JSON.stringify(leftover) }`); }
  38. /* c8 ignore stop */
  39. return unfold(unfold(clumps, ";"), ":");
  40. }
  41. /**
  42. * @_ignore
  43. */
  44. export function decodeOwl(data: string): Array<string> {
  45. assertArgument(data[0] === "0", "unsupported auwl data", "data", data);
  46. return decode(
  47. data.substring(1 + 2 * subsChrs.length),
  48. data.substring(1, 1 + 2 * subsChrs.length));
  49. }