export function parse()

in react-native-pytorch-core/src/utils/CSSFontUtils.ts [65:179]


export function parse(input: string): CSSFont | null {
  let state = ParserStates.VARIATION;
  let buffer = '';
  let result: CSSFont = {
    fontFamily: [],
  };

  for (let c, i = 0; (c = input.charAt(i)); i += 1) {
    if (state === ParserStates.BEFORE_FONT_FAMILY && (c === '"' || c === "'")) {
      let index = i + 1;

      // consume the entire string
      do {
        index = input.indexOf(c, index) + 1;
        if (!index) {
          // If a string is not closed by a ' or " return null.
          return null;
        }
      } while (input.charAt(index - 2) === '\\');

      result.fontFamily.push(input.slice(i, index));

      i = index - 1;
      state = ParserStates.FONT_FAMILY;
      buffer = '';
    } else if (state === ParserStates.FONT_FAMILY && c === ',') {
      state = ParserStates.BEFORE_FONT_FAMILY;
      buffer = '';
    } else if (state === ParserStates.BEFORE_FONT_FAMILY && c === ',') {
      const identifier = parseIdentifier(buffer);

      if (identifier) {
        result.fontFamily.push(identifier);
      }
      buffer = '';
    } else if (state === ParserStates.AFTER_OBLIQUE && c === ' ') {
      if (/^(?:\+|-)?(?:[0-9]*\.)?[0-9]+(?:deg|grad|rad|turn)$/.test(buffer)) {
        result.fontStyle += ' ' + buffer;
        buffer = '';
      } else {
        // The 'oblique' token was not followed by an angle.
        // Backtrack to allow the token to be parsed as VARIATION
        i -= 1;
      }
      state = ParserStates.VARIATION;
    } else if (state === ParserStates.VARIATION && (c === ' ' || c === '/')) {
      if (
        /^(?:(?:xx|x)-large|(?:xx|s)-small|small|large|medium)$/.test(buffer) ||
        /^(?:larg|small)er$/.test(buffer) ||
        /^(?:\+|-)?(?:[0-9]*\.)?[0-9]+(?:em|ex|ch|rem|vh|vw|vmin|vmax|px|mm|cm|in|pt|pc|%)$/.test(
          buffer,
        )
      ) {
        state =
          c === '/'
            ? ParserStates.LINE_HEIGHT
            : ParserStates.BEFORE_FONT_FAMILY;
        result.fontSize = buffer;
      } else if (/^italic$/.test(buffer)) {
        result.fontStyle = buffer;
      } else if (/^oblique$/.test(buffer)) {
        result.fontStyle = buffer;
        state = ParserStates.AFTER_OBLIQUE;
      } else if (/^small-caps$/.test(buffer)) {
        result.fontVariant = buffer;
      } else if (/^(?:bold(?:er)?|lighter)$/.test(buffer)) {
        result.fontWeight = buffer;
      } else if (
        /^[+-]?(?:[0-9]*\.)?[0-9]+(?:e[+-]?(?:0|[1-9][0-9]*))?$/.test(buffer)
      ) {
        const num = parseFloat(buffer);
        if (num >= 1 && num <= 1000) {
          result.fontWeight = buffer;
        }
      } else if (
        /^(?:(?:ultra|extra|semi)-)?(?:condensed|expanded)$/.test(buffer)
      ) {
        result.fontStretch = buffer;
      }
      buffer = '';
    } else if (state === ParserStates.LINE_HEIGHT && c === ' ') {
      if (
        /^(?:\+|-)?([0-9]*\.)?[0-9]+(?:em|ex|ch|rem|vh|vw|vmin|vmax|px|mm|cm|in|pt|pc|%)?$/.test(
          buffer,
        )
      ) {
        result.lineHeight = buffer;
      }
      state = ParserStates.BEFORE_FONT_FAMILY;
      buffer = '';
    } else {
      buffer += c;
    }
  }

  // This is for the case where a string was specified followed by
  // an identifier, but without a separating comma.
  if (state === ParserStates.FONT_FAMILY && !/^\s*$/.test(buffer)) {
    return null;
  }

  if (state === ParserStates.BEFORE_FONT_FAMILY) {
    const identifier = parseIdentifier(buffer);

    if (identifier) {
      result.fontFamily.push(identifier);
    }
  }

  if (result.fontSize && result.fontFamily.length) {
    return result;
  } else {
    return null;
  }
}