public void Build(SketchDocument document, string outputDirectory) { var symbols = document .Pages .AsEnumerable() .SelectMany(page => page.Layers.OfType <SketchSymbolMaster>()) .Where(s => NameIsValidOrLog(s.Name)) .ToList(); //We don't actually need to remove duplicates, since the ux builder will overwrite symbols with the same name anyway. LogDuplicateSymbolNames(symbols); if (!symbols.Any()) { _log.Info("No UX generated because no Sketch symbols found in sketch file. Sketchy :)"); return; } var symbolClassNameBuilder = new SymbolClassNameBuilder(); symbolClassNameBuilder.Init(symbols); var builder = new UxBuilder(symbolClassNameBuilder, new AssetEmitter(outputDirectory, _log), _log); var serializerContext = new UxSerializerContext(); // write one file per uxClass foreach (var symbol in symbols) { try { var uxClass = builder.BuildSymbolClass(symbol); ApplyTransforms(uxClass); var ux = uxClass.SerializeUx(serializerContext); var className = uxClass.Attributes["ux:Class"] as UxString; if (className != null) { if (symbol.Layers.Any()) { var outputFilePath = Path.Combine(outputDirectory, className.Value + ".ux"); try { File.WriteAllText(outputFilePath, ux); _log.Info($"Wrote '{className.Value}' to '{outputFilePath}'"); } catch (Exception e) { _log.Error("Can't write file '" + outputFilePath + "' " + e.Message); } } else { _log.Warning($"Skipping symbol '{className.Value}' which has no supported layers."); } } else { _log.Error("Can't write file for ux:Class without name"); } } catch (Exception e) { _log.Error("Failed to convert '" + symbol.Name + "': " + e.Message); } } }