Skip to content
This repository was archived by the owner on Jun 25, 2020. It is now read-only.

Commit 6ae0e48

Browse files
author
Jérémie Bertrand
committed
Merge pull request #284 from k94ll13nn3/newpost-command
New command : create new post
2 parents 9b73486 + 6718e58 commit 6ae0e48

File tree

8 files changed

+240
-1
lines changed

8 files changed

+240
-1
lines changed

src/Pretzel.Logic/Commands/CommandParameters.cs

+8-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public CommandParameters([ImportMany] IEnumerable<IHaveCommandLineArgs> commandL
3535
{ "nobrowser", "Do not launch a browser", v => LaunchBrowser = false },
3636
{ "withproject", "Includes a layout VS Solution, to give intellisense when editing razor layout files", v => WithProject = (v!=null) },
3737
{ "wiki", "Creates a wiki instead of a blog (razor template only)", v => Wiki = (v!=null) },
38-
{ "cleantarget", "Delete the target directory (_site by default)", v => CleanTarget = true }
38+
{ "cleantarget", "Delete the target directory (_site by default)", v => CleanTarget = true },
39+
{ "n|newposttitle=", "The title of the new post (\"New post\" by default)", v => NewPostTitle = v }
3940
};
4041

4142
// Allow extensions to register command line args
@@ -66,6 +67,8 @@ public CommandParameters([ImportMany] IEnumerable<IHaveCommandLineArgs> commandL
6667

6768
public string DestinationPath { get; private set; }
6869

70+
public string NewPostTitle { get; internal set; }
71+
6972
private decimal port;
7073

7174
public decimal Port
@@ -91,6 +94,10 @@ public void Parse(IEnumerable<string> arguments)
9194
{
9295
DestinationPath = fileSystem.Path.Combine(Path, DestinationPath);
9396
}
97+
if (string.IsNullOrEmpty(NewPostTitle))
98+
{
99+
NewPostTitle = "New post";
100+
}
94101
}
95102

96103
public void DetectFromDirectory(IDictionary<string, ISiteEngine> engines, SiteContext context)

src/Pretzel.Logic/Pretzel.Logic.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@
168168
<DesignTime>True</DesignTime>
169169
<DependentUpon>Resources.resx</DependentUpon>
170170
</Compile>
171+
<Compile Include="Recipe\Ingredient.cs" />
171172
<Compile Include="SanityCheck.cs" />
172173
<Compile Include="Templating\Context\Category.cs" />
173174
<Compile Include="Templating\Context\LinkHelper.cs" />
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using System.IO.Abstractions;
3+
using Pretzel.Logic.Extensibility.Extensions;
4+
using Pretzel.Logic.Extensions;
5+
6+
namespace Pretzel.Logic.Recipe
7+
{
8+
public class Ingredient
9+
{
10+
private readonly string directory;
11+
12+
private readonly IFileSystem fileSystem;
13+
14+
private readonly string title;
15+
16+
private readonly bool withDrafts;
17+
18+
public Ingredient(IFileSystem fileSystem, string title, string directory, bool withDrafts)
19+
{
20+
this.fileSystem = fileSystem;
21+
this.title = title;
22+
this.directory = directory;
23+
this.withDrafts = withDrafts;
24+
}
25+
26+
public void Create()
27+
{
28+
var postPath = fileSystem.Path.Combine(directory, !this.withDrafts ? @"_posts" : @"_drafts");
29+
30+
var postName = string.Format("{0}-{1}.md", DateTime.Today.ToString("yyyy-MM-dd"), SlugifyFilter.Slugify(title));
31+
var pageContents = string.Format("---\r\n layout: post \r\n title: {0}\r\n comments: true\r\n---\r\n", title);
32+
33+
if (!fileSystem.Directory.Exists(postPath))
34+
{
35+
Tracing.Info(string.Format("{0} folder not found", postPath));
36+
return;
37+
}
38+
39+
if (fileSystem.File.Exists(fileSystem.Path.Combine(postPath, postName)))
40+
{
41+
Tracing.Info(string.Format("The \"{0}\" file already exists", postName));
42+
return;
43+
}
44+
45+
fileSystem.File.WriteAllText(fileSystem.Path.Combine(postPath, postName), pageContents);
46+
47+
Tracing.Info(string.Format("Created the \"{0}\" post ({1})", title, postName));
48+
}
49+
}
50+
}

src/Pretzel.Tests/Commands/CommandParameterTests.cs

+41
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public class CommandParameterTests
2222
private const string ExpectedPort = "8000";
2323
private const decimal ExpectedPortDecimal = 8000;
2424
private const string ExpectedDestinationPath = @"D:\Code\Generated";
25+
private const string ExpectedNewPostTitle = @"Post title";
2526

2627
private readonly IFileSystem FileSystem = new MockFileSystem();
2728

@@ -236,6 +237,38 @@ public void LaunchBrowser_WhenNotSpecifyingCleanTarget_IsFalse()
236237
Assert.False(subject.CleanTarget);
237238
}
238239

240+
[Fact]
241+
public void Parse_WhenSpecifyingNewPostTitleUsingShortParameter_MapsToPath()
242+
{
243+
var args = new List<string> { "--n", ExpectedNewPostTitle };
244+
subject.Parse(args);
245+
Assert.Equal(ExpectedNewPostTitle, subject.NewPostTitle);
246+
}
247+
248+
[Fact]
249+
public void Parse_WhenSpecifyingNewPostTitleUsingFullParameter_MapsToPath()
250+
{
251+
var args = new List<string> { "--newposttitle", ExpectedNewPostTitle };
252+
subject.Parse(args);
253+
Assert.Equal(ExpectedNewPostTitle, subject.NewPostTitle);
254+
}
255+
256+
[Fact]
257+
public void Parse_WhenSpecifyingNewPostTitleUsingShortParameterSingleDash_MapsToPath()
258+
{
259+
var args = new List<string> { "-n", ExpectedNewPostTitle };
260+
subject.Parse(args);
261+
Assert.Equal(ExpectedNewPostTitle, subject.NewPostTitle);
262+
}
263+
264+
[Fact]
265+
public void Parse_WhenSpecifyingNewPostTitleUsingFullParameterSingleDash_MapsToPath()
266+
{
267+
var args = new List<string> { "-newposttitle", ExpectedNewPostTitle };
268+
subject.Parse(args);
269+
Assert.Equal(ExpectedNewPostTitle, subject.NewPostTitle);
270+
}
271+
239272
[Fact]
240273
public void CommandParameters_WhenSpecifyingAllParameters_ResultIsCorrect()
241274
{
@@ -410,5 +443,13 @@ public void Parse_WhenNoParametersSet_MapsDestinationPathTo_siteInCurrentDirecto
410443
subject.Parse(args);
411444
Assert.Equal(FileSystem.Path.Combine(subject.Path, "_site"), subject.DestinationPath);
412445
}
446+
447+
[Fact]
448+
public void Parse_WhenNoParametersSet_MapsNewPostTileToNewPost()
449+
{
450+
var args = new List<string>();
451+
subject.Parse(args);
452+
Assert.Equal("New post", subject.NewPostTitle);
453+
}
413454
}
414455
}

src/Pretzel.Tests/Pretzel.Tests.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
<Compile Include="MockAssembly.cs" />
107107
<Compile Include="PretzelContext.cs" />
108108
<Compile Include="Properties\AssemblyInfo.cs" />
109+
<Compile Include="Recipe\IngredientTests.cs" />
109110
<Compile Include="Recipe\RecipeTests.cs" />
110111
<Compile Include="Templating\Context\LinkHelperTest.cs" />
111112
<Compile Include="Templating\Context\SiteContextGeneratorTests.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
using NSubstitute;
2+
using Pretzel.Logic.Extensibility;
3+
using Pretzel.Logic.Extensibility.Extensions;
4+
using Pretzel.Logic.Extensions;
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Globalization;
8+
using System.IO;
9+
using System.IO.Abstractions;
10+
using System.IO.Abstractions.TestingHelpers;
11+
using System.Linq;
12+
using System.Text;
13+
using System.Threading;
14+
using Xunit;
15+
using Xunit.Extensions;
16+
17+
namespace Pretzel.Tests.Recipe
18+
{
19+
public class IngredientTests
20+
{
21+
private MockFileSystem fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>());
22+
private const string BaseSite = @"c:\site\";
23+
private const string PostsFolder = @"_posts";
24+
private const string DraftsFolder = @"_drafts";
25+
26+
private readonly StringBuilder sb = new StringBuilder();
27+
private readonly TextWriter writer;
28+
29+
public IngredientTests()
30+
{
31+
writer = new StringWriter(sb);
32+
Tracing.Logger.SetWriter(writer);
33+
Tracing.Logger.AddCategory(Tracing.Category.Info);
34+
Tracing.Logger.AddCategory(Tracing.Category.Error);
35+
Tracing.Logger.AddCategory(Tracing.Category.Debug);
36+
}
37+
38+
[Fact]
39+
public void Post_Is_Created()
40+
{
41+
fileSystem.Directory.CreateDirectory(BaseSite + PostsFolder);
42+
var postTitle = "Post title";
43+
var postName = string.Format("{0}-{1}.md", DateTime.Today.ToString("yyyy-MM-dd"), SlugifyFilter.Slugify(postTitle));
44+
45+
var ingredient = new Logic.Recipe.Ingredient(fileSystem, postTitle, BaseSite, false);
46+
ingredient.Create();
47+
48+
Assert.True(fileSystem.File.Exists(fileSystem.Path.Combine(BaseSite + PostsFolder, postName)));
49+
}
50+
51+
[Fact]
52+
public void Post_Has_Correct_Content()
53+
{
54+
fileSystem.Directory.CreateDirectory(BaseSite + PostsFolder);
55+
var postTitle = "Post title";
56+
var expectedContent = string.Format("---\r\n layout: post \r\n title: {0}\r\n comments: true\r\n---\r\n", postTitle);
57+
var postName = string.Format("{0}-{1}.md", DateTime.Today.ToString("yyyy-MM-dd"), SlugifyFilter.Slugify(postTitle));
58+
59+
var ingredient = new Logic.Recipe.Ingredient(fileSystem, "Post title", BaseSite, false);
60+
ingredient.Create();
61+
62+
Assert.Equal(expectedContent, fileSystem.File.ReadAllText(fileSystem.Path.Combine(BaseSite + PostsFolder, postName)));
63+
}
64+
65+
[Fact]
66+
public void Post_Already_Exists()
67+
{
68+
fileSystem.Directory.CreateDirectory(BaseSite + PostsFolder);
69+
var postTitle = "Post title";
70+
var postName = string.Format("{0}-{1}.md", DateTime.Today.ToString("yyyy-MM-dd"), SlugifyFilter.Slugify(postTitle));
71+
72+
var ingredient = new Logic.Recipe.Ingredient(fileSystem, postTitle, BaseSite, false);
73+
ingredient.Create();
74+
ingredient.Create();
75+
76+
Assert.Contains(string.Format("The \"{0}\" file already exists", postName), writer.ToString());
77+
}
78+
79+
[Fact]
80+
public void Post_Folder_Not_Found()
81+
{
82+
var ingredient = new Logic.Recipe.Ingredient(fileSystem, string.Empty, BaseSite, false);
83+
ingredient.Create();
84+
85+
Assert.Contains(string.Format(@"{0} folder not found", BaseSite + PostsFolder), writer.ToString());
86+
}
87+
88+
[Fact]
89+
public void Draft_Folder_Not_Found()
90+
{
91+
var ingredient = new Logic.Recipe.Ingredient(fileSystem, string.Empty, BaseSite, true);
92+
ingredient.Create();
93+
94+
Assert.Contains(string.Format(@"{0} folder not found", BaseSite + DraftsFolder), writer.ToString());
95+
}
96+
}
97+
}
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Pretzel.Logic.Commands;
2+
using Pretzel.Logic.Extensions;
3+
using Pretzel.Logic.Recipe;
4+
using System.Collections.Generic;
5+
using System.ComponentModel.Composition;
6+
using System.IO;
7+
using System.IO.Abstractions;
8+
9+
namespace Pretzel.Commands
10+
{
11+
[PartCreationPolicy(CreationPolicy.Shared)]
12+
[CommandInfo(CommandName = "ingredient")]
13+
public sealed class IngredientCommand : ICommand
14+
{
15+
#pragma warning disable 649
16+
17+
[Import]
18+
private IFileSystem fileSystem;
19+
20+
[Import]
21+
private CommandParameters parameters;
22+
23+
#pragma warning restore 649
24+
25+
public void Execute(IEnumerable<string> arguments)
26+
{
27+
Tracing.Info("ingredient - create a new post");
28+
29+
parameters.Parse(arguments);
30+
31+
var ingredient = new Ingredient(fileSystem, parameters.NewPostTitle, parameters.Path, parameters.IncludeDrafts);
32+
ingredient.Create();
33+
}
34+
35+
public void WriteHelp(TextWriter writer)
36+
{
37+
writer.Write(" Create a new post\r\n");
38+
parameters.WriteOptions(writer, "newposttitle", "drafts", "-s");
39+
}
40+
}
41+
}

src/Pretzel/Pretzel.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@
132132
<Compile Include="Commands\CommandInfoAttribute.cs" />
133133
<Compile Include="Commands\HungryCommand.cs" />
134134
<Compile Include="Commands\ImportCommand.cs" />
135+
<Compile Include="Commands\IngredientCommand.cs" />
135136
<Compile Include="Commands\RecipeCommand.cs" />
136137
<Compile Include="Commands\ICommand.cs" />
137138
<Compile Include="Commands\ICommandInfo.cs" />

0 commit comments

Comments
 (0)