export function androidSerializePattern()

in js/src/android-serialize.ts [25:106]


export function androidSerializePattern(
  pattern: Pattern,
  onError: (error: SerializeError) => void
): string {
  if (
    pattern.length === 1 &&
    isExpression(pattern[0]) &&
    pattern[0].fn === 'reference'
  ) {
    // Android resource reference
    const arg = pattern[0]._ ?? ''
    if (!resoureRef.test(arg)) {
      const error = `android: Invalid reference: ${JSON.stringify(pattern[0])}`
      onError(new SerializeError(error))
    }
    return arg
  }

  const entities: Record<string, string> = {}
  const doc = new DOMParser().parseFromString(
    '<string xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"></string>',
    'text/xml'
  )
  const root = doc.querySelector('string')!
  let node = root
  for (const part of pattern) {
    if (typeof part === 'string') {
      appendText(node, escape(part))
    } else if (isExpression(part)) {
      if (part.attr?.translate == 'no') {
        const xliffg = doc.createElementNS(xliffNS, 'xliff:g')
        for (const error of setAttributes(xliffg, part.opt)) {
          onError(new SerializeError(`android: ${error}`))
        }
        xliffg.appendChild(new Text(asTextContent(part, entities, onError)))
        node.appendChild(xliffg)
      } else {
        appendText(node, asTextContent(part, entities, onError))
      }
    } else if (part.open) {
      const child = doc.createElementNS(
        part.open.startsWith('xliff:') ? xliffNS : null,
        part.open
      )
      for (const error of setAttributes(child, part.opt)) {
        onError(new SerializeError(`android: ${error}`))
      }
      node.appendChild(child)
      node = child
    } else if (part.close) {
      if (part.opt && Object.keys(part.opt).length) {
        const error = `android: Options on closing markup are not supported: ${JSON.stringify(part)}`
        onError(new SerializeError(error))
      }
      if (node !== root && node.tagName === part.close && node.parentElement) {
        node = node.parentElement
      } else {
        const error = `android: Improper element nesting for <${node.tagName}>`
        onError(new SerializeError(error))
      }
    } else {
      const error = `android: Unsupported markup ${JSON.stringify(part)}`
      onError(new SerializeError(error))
    }
  }
  if (node !== root) {
    const error = `android: Missing closing markup for ${node.tagName}`
    onError(new SerializeError(error))
  }
  quoteAndroidSpaces(root, true)
  let str: string
  try {
    str = serialize(root)
  } catch (error) {
    onError(new SerializeError(`xliff: ${error}`))
    return ERROR_RESULT
  }
  for (const [key, entity] of Object.entries(entities)) {
    str = str.replace(key, entity)
  }
  return str
}