blob: 343b61f97b2b161eb7505bcecb5d23cb0a9e61ae [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/**
* This library is used to convert data from a map to a YAML string.
*/
library dart2yaml;
import 'dart:collection';
/**
* Gets a String representing the input Map in YAML format.
*/
String getYamlString(Map documentData) {
StringBuffer yaml = new StringBuffer();
_addLevel(yaml, documentData, 0);
return yaml.toString();
}
/**
* This recursive function builds a YAML string from [documentData] and
* adds it to [yaml].
* The [level] input determines the indentation of the block being processed.
* The [isList] input determines whether [documentData] is a member of an outer
* lists of maps. A map must be preceeded with a '-' if it is to exist at the
* same level of indentation in the YAML output as other members of the list.
*/
void _addLevel(StringBuffer yaml, Map documentData, int level,
{bool isList: false}) {
// The order of the keys could be nondeterministic, but it is insufficient
// to just sort the keys no matter what, as their order could be significant
// (i.e. parameters to a method). The order of the keys should be enforced
// by the caller of this function.
var keys = documentData.keys.toList();
keys.forEach((key) {
_calcSpaces(level, yaml);
// Only the first entry of the map should be preceeded with a '-' since
// the map is a member of an outer list and the map as a whole must be
// marked as a single member of that list. See example 2.4 at
// http://www.yaml.org/spec/1.2/spec.html#id2759963
if (isList && key == keys.first) {
yaml.write("- ");
level++;
}
yaml.write("\"$key\" : ");
if (documentData[key] is Map) {
yaml.write("\n");
_addLevel(yaml, documentData[key], level + 1);
} else if (documentData[key] is List) {
var elements = documentData[key];
yaml.write("\n");
elements.forEach( (element) {
if (element is Map) {
_addLevel(yaml, element, level + 1, isList: true);
} else {
_calcSpaces(level + 1, yaml);
yaml.write("- ${_processElement(element)}");
}
});
} else {
yaml.write(_processElement(documentData[key]));
}
});
}
/**
* Returns an escaped String form of the inputted element.
*/
String _processElement(var element) {
var contents = element.toString()
.replaceAll('\\', r'\\')
.replaceAll('"', r'\"')
.replaceAll('\n', r'\n');
return '"$contents"\n';
}
/**
* Based on the depth in the file, this function returns the correct spacing
* for an element in the YAML output.
*/
void _calcSpaces(int spaceLevel, StringBuffer yaml) {
for (int i = 0; i < spaceLevel; i++) {
yaml.write(" ");
}
}