parseExport static method

List<Map<String, dynamic>> parseExport(
  1. String raw
)

Parse raw export text (JSON, CSV, or newline-delimited URLs) into links.

Implementation

static List<Map<String, dynamic>> parseExport(String raw) {
  final text = raw.trim();
  if (text.isEmpty) throw FdlParseError('Export is empty.');

  // Try JSON first.
  if (text[0] == '{' || text[0] == '[') {
    final dynamic json;
    try {
      json = jsonDecode(text);
    } catch (e) {
      throw FdlParseError('Export looks like JSON but failed to parse: $e');
    }
    final List<dynamic> arr;
    if (json is List) {
      arr = json;
    } else if (json is Map && json['links'] is List) {
      arr = json['links'] as List;
    } else if (json is Map && json['shortLinks'] is List) {
      arr = json['shortLinks'] as List;
    } else {
      arr = [json];
    }
    if (arr.isEmpty) throw FdlParseError('Export contained zero links.');
    final out = <Map<String, dynamic>>[];
    for (var i = 0; i < arr.length; i++) {
      try {
        out.add(_normalizeObject(arr[i]));
      } on FdlParseError catch (e) {
        throw FdlParseError('Link #${i + 1}: ${e.message}');
      }
    }
    return out;
  }

  // Otherwise treat as newline-delimited content (ignore blanks/# comments).
  final lines = text
      .split(RegExp(r'\r?\n'))
      .map((l) => l.trim())
      .where((l) => l.isNotEmpty && !l.startsWith('#'))
      .toList();
  if (lines.isEmpty) throw FdlParseError('Export contained zero links.');

  // A CSV export has a header row: the first content line has a comma and does
  // NOT start with a URL (header cells are column names). A bare-URL list and
  // an FDL long-link list both start with `http`, so they stay on the URL path
  // even though long links contain commas in their query values.
  final first = lines[0];
  if (first.contains(',') &&
      !RegExp(r'^https?://', caseSensitive: false).hasMatch(first)) {
    return parseCsv(lines);
  }

  final out = <Map<String, dynamic>>[];
  for (var i = 0; i < lines.length; i++) {
    try {
      out.add(parseUrl(lines[i]));
    } on FdlParseError catch (e) {
      throw FdlParseError('Line #${i + 1}: ${e.message}');
    }
  }
  return out;
}