diff --git a/source/Models/CommandLineOptions/NewSiteOptions.cs b/source/Models/CommandLineOptions/NewSiteOptions.cs new file mode 100644 index 0000000000000000000000000000000000000000..c9fb348eb0343cf235f3327fd7b1e21b9cb2792e --- /dev/null +++ b/source/Models/CommandLineOptions/NewSiteOptions.cs @@ -0,0 +1,40 @@ +using CommandLine; + +namespace SuCoS.Models.CommandLineOptions; + +/// +/// Command line options to generate a simple site from scratch. +/// +[Verb("newsite", false, HelpText = "Generate a simple site from scratch")] +public class NewSiteOptions +{ + /// + /// The path of the output files. + /// + [Option('o', "output", Required = false, HelpText = "Output directory path")] + public required string Output { get; init; } + + /// + /// Force site creation. + /// + [Option('f', "force", Required = false, HelpText = "Force site creation")] + public bool Force { get; init; } + + /// + /// Site title. + /// + [Option("title", Required = false, HelpText = "Site title")] + public required string Title { get; init; } = "My Site"; + + /// + /// Site description. + /// + [Option("description", Required = false, HelpText = "Site description")] + public required string Description { get; init; } = string.Empty; + + /// + /// Site base url. + /// + [Option("url", Required = false, HelpText = "Site base url")] + public required string BaseURL { get; init; } = "https://example.org/"; +} diff --git a/source/Models/Site.cs b/source/Models/Site.cs index 4b56ce34943440194a34f0a4431d05289e72e550..f6f26d77e9548f1f6847ea63f358570da327fdc3 100644 --- a/source/Models/Site.cs +++ b/source/Models/Site.cs @@ -78,6 +78,15 @@ public class Site : ISite /// public string SourceThemeStaticPath => Path.Combine(SourceThemePath, "static"); + /// + /// List of all basic source folders + /// + public IEnumerable SourceFodlers => [ + SourceContentPath, + SourceStaticPath, + SourceThemePath + ]; + /// /// List of all pages, including generated. /// diff --git a/source/NewSiteCommand.cs b/source/NewSiteCommand.cs new file mode 100644 index 0000000000000000000000000000000000000000..7d01736d791737e00a626e42e48407d498686e0b --- /dev/null +++ b/source/NewSiteCommand.cs @@ -0,0 +1,89 @@ +using Serilog; +using SuCoS.Models; +using SuCoS.Models.CommandLineOptions; +using YamlDotNet.Serialization; + +namespace SuCoS; + +/// +/// Check links of a given site. +/// +public sealed partial class NewSiteCommand(NewSiteOptions settings, ILogger logger) +{ + /// + /// Run the app + /// + /// + public int Run() + { + var siteSettings = new SiteSettings() + { + Title = settings.Title, + Description = settings.Description, + BaseURL = settings.BaseURL, + }; + + // TODO: Refactor Site class to not need YAML parser nor FrontMatterParser + var site = new Site(new ServeOptions() { SourceOption = settings.Output }, siteSettings, null!, logger, null); + + var outputPath = Path.GetFullPath(settings.Output); + var siteSettingsPath = Path.Combine(outputPath, "sucos.yaml"); + + if (File.Exists(siteSettingsPath) && !settings.Force) + { + logger.Error("{directoryPath} already exists", outputPath); + return 1; + } + + logger.Information("Creating a new site: {title} at {outputPath}", siteSettings.Title, outputPath); + + CreateFolders(site.SourceFodlers); + + try + { + ExportSiteSettings(siteSettings, siteSettingsPath); + } + catch (Exception ex) + { + logger.Error("Failed to export site settings: {ex}", ex); + return 1; + } + logger.Information("Done"); + + return 0; + } + + /// + /// Create the standard folders + /// + /// + private void CreateFolders(IEnumerable folders) + { + foreach (var folder in folders) + { + logger.Information("Creating {folder}", folder); + Directory.CreateDirectory(folder); + } + } + + // TODO: move all YAML parsing to this own class + #region YAML + /// + /// YamlDotNet parser to loosely parse the YAML file. Used to include all non-matching fields + /// into Params. + /// + ISerializer yamlDeserializer = new SerializerBuilder() + .IgnoreFields() + .ConfigureDefaultValuesHandling( + DefaultValuesHandling.OmitEmptyCollections + | DefaultValuesHandling.OmitDefaults + | DefaultValuesHandling.OmitNull) + .Build(); + + void ExportSiteSettings(SiteSettings siteSettings, string siteSettingsPath) + { + var siteSettingsConverted = yamlDeserializer.Serialize(siteSettings); + File.WriteAllText(siteSettingsPath, siteSettingsConverted); + } + #endregion YAML +} \ No newline at end of file diff --git a/source/Program.cs b/source/Program.cs index ab464322857b54b289e972ee39577f9a2d00ba1f..02a810e8cb082df4996170619c7845c01498cc2b 100644 --- a/source/Program.cs +++ b/source/Program.cs @@ -43,7 +43,7 @@ public class Program(ILogger logger) { OutputLogo(); OutputWelcome(); - return await CommandLine.Parser.Default.ParseArguments(args) + return await CommandLine.Parser.Default.ParseArguments(args) .WithParsed(options => { logger = CreateLogger(options.Verbose); @@ -90,8 +90,14 @@ public class Program(ILogger logger) }, (CheckLinkOptions options) => { + logger = CreateLogger(options.Verbose); var command = new CheckLinkCommand(options, logger); return command.Run(); + }, + (NewSiteOptions options) => + { + var command = new NewSiteCommand(options, logger); + return Task.FromResult(command.Run()); }, errs => Task.FromResult(1) );