├── .gitattributes
├── .gitignore
├── MiniBlogFormatter.sln
├── MiniBlogFormatter
├── App.config
├── Formatters
│ ├── BlogEngineFormatter.cs
│ ├── BlogMLFormatter.cs
│ ├── DasBlogFormatter.cs
│ ├── FormatterHelpers.cs
│ ├── GhostFormatter.cs
│ └── WordpressFormatter.cs
├── MiniBlogFormatter.csproj
├── Models
│ ├── Comment.cs
│ ├── GhostData.cs
│ ├── Post.cs
│ └── Storage.cs
├── Program.cs
└── packages.config
├── README.md
└── packages
└── Newtonsoft.Json.6.0.6
├── Newtonsoft.Json.6.0.6.nupkg
├── lib
├── net20
│ ├── Newtonsoft.Json.dll
│ └── Newtonsoft.Json.xml
├── net35
│ ├── Newtonsoft.Json.dll
│ └── Newtonsoft.Json.xml
├── net40
│ ├── Newtonsoft.Json.dll
│ └── Newtonsoft.Json.xml
├── net45
│ ├── Newtonsoft.Json.dll
│ └── Newtonsoft.Json.xml
├── netcore45
│ ├── Newtonsoft.Json.dll
│ └── Newtonsoft.Json.xml
├── portable-net40+sl5+wp80+win8+wpa81
│ ├── Newtonsoft.Json.dll
│ └── Newtonsoft.Json.xml
└── portable-net45+wp80+win8+wpa81+aspnetcore50
│ ├── Newtonsoft.Json.dll
│ └── Newtonsoft.Json.xml
└── tools
└── install.ps1
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 |
46 | [Dd]ebug/
47 | [Rr]elease/
48 | x64/
49 | build/
50 | [Bb]in/
51 | [Oo]bj/
52 |
53 | # MSTest test Results
54 | [Tt]est[Rr]esult*/
55 | [Bb]uild[Ll]og.*
56 |
57 | *_i.c
58 | *_p.c
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.log
79 | *.scc
80 |
81 | # Visual C++ cache files
82 | ipch/
83 | *.aps
84 | *.ncb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | *.ncrunch*
109 | .*crunch*.local.xml
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.Publish.xml
129 | *.pubxml
130 |
131 | # NuGet Packages Directory
132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
133 | #packages/
134 |
135 | # Windows Azure Build Output
136 | csx
137 | *.build.csdef
138 |
139 | # Windows Store app package directory
140 | AppPackages/
141 |
142 | # Others
143 | sql/
144 | *.Cache
145 | ClientBin/
146 | [Ss]tyle[Cc]op.*
147 | ~$*
148 | *~
149 | *.dbmdl
150 | *.[Pp]ublish.xml
151 | *.pfx
152 | *.publishsettings
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | App_Data/*.mdf
166 | App_Data/*.ldf
167 |
168 | #############
169 | ## Windows detritus
170 | #############
171 |
172 | # Windows image file caches
173 | Thumbs.db
174 | ehthumbs.db
175 |
176 | # Folder config file
177 | Desktop.ini
178 |
179 | # Recycle Bin used on file shares
180 | $RECYCLE.BIN/
181 |
182 | # Mac crap
183 | .DS_Store
184 |
185 |
186 | #############
187 | ## Python
188 | #############
189 |
190 | *.py[co]
191 |
192 | # Packages
193 | *.egg
194 | *.egg-info
195 | dist/
196 | build/
197 | eggs/
198 | parts/
199 | var/
200 | sdist/
201 | develop-eggs/
202 | .installed.cfg
203 |
204 | # Installer logs
205 | pip-log.txt
206 |
207 | # Unit test / coverage reports
208 | .coverage
209 | .tox
210 |
211 | #Translations
212 | *.mo
213 |
214 | #Mr Developer
215 | .mr.developer.cfg
216 |
--------------------------------------------------------------------------------
/MiniBlogFormatter.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.20919.2
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniBlogFormatter", "MiniBlogFormatter\MiniBlogFormatter.csproj", "{B92EB6D7-8C50-481C-B68D-A7C04CAFF65C}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {B92EB6D7-8C50-481C-B68D-A7C04CAFF65C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {B92EB6D7-8C50-481C-B68D-A7C04CAFF65C}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {B92EB6D7-8C50-481C-B68D-A7C04CAFF65C}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {B92EB6D7-8C50-481C-B68D-A7C04CAFF65C}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/Formatters/BlogEngineFormatter.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Text.RegularExpressions;
3 | using System.Xml;
4 |
5 | namespace MiniBlogFormatter
6 | {
7 | public class BlogEngineFormatter
8 | {
9 | private Regex rxFiles = new Regex("(href|src)=\"(([^\"]+)?(file|image)\\.axd\\?(file|picture)=([^\"]+))\"", RegexOptions.IgnoreCase);
10 | private Regex rxAggBug = new Regex("
", RegexOptions.IgnoreCase);
11 |
12 | public void Format(string fileName, string targetFolderPath, string categoriesFileName)
13 | {
14 | XmlDocument doc = new XmlDocument();
15 | doc.Load(fileName);
16 |
17 | XmlNode isDeletedNode = doc.SelectSingleNode("post/isdeleted");
18 |
19 | bool isDeleted = isDeletedNode != null ? isDeletedNode.InnerText == "True" : false;
20 |
21 | if (!isDeleted)
22 | {
23 | FormatSlug(doc);
24 | FormatFileReferences(doc);
25 | RemoveAggBug(doc);
26 | RemoveSpamComments(doc);
27 |
28 | XmlDocument categories = new XmlDocument();
29 | categories.Load(categoriesFileName);
30 | FormatCategories(doc, categories);
31 |
32 | string newFileName = Path.Combine(targetFolderPath, Path.GetFileName(fileName));
33 | doc.Save(newFileName);
34 | }
35 | }
36 |
37 | private void FormatFileReferences(XmlDocument doc)
38 | {
39 | XmlNode content = doc.SelectSingleNode("post/content");
40 |
41 | if (content != null)
42 | {
43 | foreach (Match match in rxFiles.Matches(content.InnerText))
44 | {
45 | content.InnerText = content.InnerText.Replace(match.Groups[2].Value, "/posts/files/" + match.Groups[6].Value);
46 | }
47 | }
48 | }
49 |
50 | private void FormatSlug(XmlDocument doc)
51 | {
52 | XmlNode slug = doc.SelectSingleNode("//slug");
53 |
54 | if (slug != null)
55 | {
56 | slug.InnerText = FormatterHelpers.FormatSlug(slug.InnerText);
57 | }
58 | }
59 |
60 | private void RemoveAggBug(XmlDocument doc)
61 | {
62 | XmlNode content = doc.SelectSingleNode("post/content");
63 |
64 | if (content != null)
65 | {
66 | content.InnerText = rxAggBug.Replace(content.InnerText, string.Empty);
67 | }
68 | }
69 |
70 | private void RemoveSpamComments(XmlDocument doc)
71 | {
72 | XmlNodeList comments = doc.SelectNodes("//comment");
73 |
74 | for (int i = comments.Count - 1; i > -1; i--)
75 | {
76 | XmlNode comment = comments[i];
77 | bool approved = comment.Attributes["approved"] != null ? comment.Attributes["approved"].InnerText == "True" : true;
78 | bool deleted = comment.Attributes["deleted"] != null ? comment.Attributes["deleted"].InnerText == "True" : true;
79 |
80 | if (!approved || deleted)
81 | {
82 | comment.ParentNode.RemoveChild(comment);
83 | }
84 | }
85 | }
86 |
87 | private void FormatCategories(XmlDocument doc, XmlDocument categoriesDoc)
88 | {
89 | XmlNodeList categories = doc.SelectNodes("//category");
90 |
91 | foreach (XmlNode category in categories)
92 | {
93 | string id = category.InnerText;
94 | XmlNode name = categoriesDoc.SelectSingleNode("//category[@id='" + id + "']");
95 |
96 | if (name != null)
97 | {
98 | category.InnerText = name.InnerText;
99 | }
100 | }
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/Formatters/BlogMLFormatter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using System.Xml.Linq;
8 |
9 | namespace MiniBlogFormatter
10 | {
11 | public class BlogMLFormatter
12 | {
13 | XNamespace ns = "http://www.blogml.com/2006/09/BlogML";
14 |
15 | public void Format(string fileName, string targetFolderPath)
16 | {
17 | XDocument doc = XDocument.Load(fileName);
18 |
19 | Dictionary authors = doc.Root.Element(ns + "authors").Elements(ns + "author").ToDictionary(x => x.Attribute("id").Value, x => x.Element(ns + "title").Value);
20 | Dictionary categories = doc.Root.Element(ns + "categories").Elements(ns + "category").ToDictionary(x => x.Attribute("id").Value, x => x.Element(ns + "title").Value);
21 |
22 | foreach (XElement postData in doc.Root.Element(ns + "posts").Elements(ns + "post"))
23 | {
24 | Post post = ParsePost(postData, authors, categories);
25 |
26 | Storage.Save(post, Path.Combine(targetFolderPath, post.ID + ".xml"));
27 | }
28 | }
29 |
30 | public void ConvertFromBase64(string fileName, string targetFileName)
31 | {
32 | XDocument doc = XDocument.Load(fileName);
33 | var query = doc.Descendants(ns + "content")
34 | .Where(node => (string)node.Attribute("type") == "base64");
35 | foreach (var item in query)
36 | {
37 | var content = Encoding.UTF8.GetString(Convert.FromBase64String(item.Value));
38 |
39 | item.SetValue(content);
40 | }
41 |
42 | doc.Save(targetFileName);
43 | }
44 |
45 | Post ParsePost(XElement postData, Dictionary authors, Dictionary categories)
46 | {
47 | Post post = new Post()
48 | {
49 | Title = postData.Element(ns + "title").Value,
50 | Content = postData.Element(ns + "content").Value,
51 | PubDate = (DateTime)postData.Attribute("date-created"),
52 | LastModified = (DateTime)postData.Attribute("date-modified"),
53 | IsPublished = (bool)postData.Attribute("approved"),
54 | Categories = postData.Descendants(ns + "category").Select(x => categories[x.Attribute("ref").Value]).ToArray()
55 | };
56 |
57 | XElement name = postData.Element(ns + "post-name");
58 |
59 | if (name != null)
60 | post.Slug = name.Value;
61 | else
62 | post.Slug = FormatterHelpers.FormatSlug(post.Title);
63 |
64 | XElement author = postData.Descendants(ns + "author").FirstOrDefault();
65 |
66 | if (author != null)
67 | {
68 | var thisArthor = author.Attribute("ref").Value;
69 | foreach(var thisKey in authors.Keys)
70 | {
71 | // Fixes issue when author name has different cases from the Key value of Authors
72 | if(thisArthor.Equals(thisKey, StringComparison.CurrentCultureIgnoreCase))
73 | {
74 | post.Author = authors[thisKey];
75 | }
76 | }
77 | }
78 |
79 | foreach (XElement commentData in postData.Descendants(ns + "comment"))
80 | {
81 | if (commentData.Attribute("approved").Value == "true")
82 | {
83 | post.Comments.Add(new Comment()
84 | {
85 | ID = commentData.Attribute("id").Value,
86 | PubDate = (DateTime)commentData.Attribute("date-created"),
87 | Content = commentData.Element(ns + "content").Value,
88 | Author = (string)commentData.Attribute("user-name"),
89 | Website = (string)commentData.Attribute("user-url"),
90 | Email = (string)commentData.Attribute("user-email"),
91 | });
92 | }
93 | }
94 |
95 | return post;
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/Formatters/DasBlogFormatter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Text.RegularExpressions;
5 | using System.Xml;
6 | using System.Linq;
7 |
8 | namespace MiniBlogFormatter
9 | {
10 | public class DasBlogFormatter
11 | {
12 | private Regex rxFiles = new Regex("(href|src)=\"(([^\"]+)(/content/binary/)([^\"]+))\"", RegexOptions.IgnoreCase);
13 |
14 | public void Format(string originalFolderPath, string targetFolderPath)
15 | {
16 | FormatPosts(originalFolderPath, targetFolderPath);
17 | FormatComments(originalFolderPath, targetFolderPath);
18 | }
19 |
20 | private void FormatPosts(string originalFolderPath, string targetFolderPath)
21 | {
22 | foreach (string file in Directory.GetFiles(originalFolderPath, "*.xml"))
23 | {
24 | if (!file.EndsWith("dayentry.xml", StringComparison.OrdinalIgnoreCase))
25 | continue;
26 |
27 | XmlDocument docOrig = LoadDocument(file);
28 | XmlNamespaceManager nsm = LoadNamespaceManager(docOrig);
29 |
30 | foreach (XmlNode entry in docOrig.SelectNodes("//Entry", nsm))
31 | {
32 | Post post = new Post();
33 | post.Categories = FormatCategories(entry.SelectSingleNode("Categories")).ToArray();
34 | post.Title = entry.SelectSingleNode("Title").InnerText;
35 | post.Slug = FormatterHelpers.FormatSlug(post.Title);
36 | post.PubDate = DateTime.Parse(entry.SelectSingleNode("//Created").InnerText);
37 | post.LastModified = DateTime.Parse(entry.SelectSingleNode("//Modified").InnerText);
38 | post.Content = FormatFileReferences(entry.SelectSingleNode("Content").InnerText);
39 | post.Author = entry.SelectSingleNode("Author").InnerText;
40 | post.IsPublished = bool.Parse(ReadValue(entry.SelectSingleNode("IsPublic"), "true"));
41 |
42 | string newFile = Path.Combine(targetFolderPath, entry.SelectSingleNode("EntryId").InnerText + ".xml");
43 | Storage.Save(post, newFile);
44 | }
45 | }
46 | }
47 |
48 | private string FormatFileReferences(string content)
49 | {
50 | foreach (Match match in rxFiles.Matches(content))
51 | {
52 | content = content.Replace(match.Groups[2].Value, "/posts/files/" + match.Groups[5].Value);
53 | }
54 |
55 | return content;
56 | }
57 |
58 | private static XmlNamespaceManager LoadNamespaceManager(XmlDocument docOrig)
59 | {
60 | XmlNamespaceManager nsm = new XmlNamespaceManager(docOrig.NameTable);
61 | nsm.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
62 | nsm.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
63 | return nsm;
64 | }
65 |
66 | private void FormatComments(string originalFolderPath, string targetFolderPath)
67 | {
68 | foreach (string file in Directory.GetFiles(originalFolderPath, "*.xml"))
69 | {
70 | if (!file.EndsWith("dayfeedback.xml", StringComparison.OrdinalIgnoreCase))
71 | continue;
72 |
73 | XmlDocument docOrig = LoadDocument(file);
74 | XmlNamespaceManager nsm = LoadNamespaceManager(docOrig);
75 |
76 | foreach (XmlNode entry in docOrig.SelectNodes("//Comment", nsm))
77 | {
78 | XmlNode idNode = entry.SelectSingleNode("TargetEntryId");
79 | string postFile = Path.Combine(targetFolderPath, idNode.InnerText + ".xml");
80 |
81 | if (!File.Exists(postFile))
82 | continue;
83 |
84 | bool isSpam = ReadValue(entry.SelectSingleNode("SpamState"), "n/a") == "Spam";
85 | if (isSpam)
86 | continue;
87 |
88 | Post post = Storage.LoadPost(postFile);
89 |
90 | Comment comment = new Comment();
91 | comment.Author = ReadValue(entry.SelectSingleNode("Author"), "n/a");
92 | comment.Email = ReadValue(entry.SelectSingleNode("AuthorEmail"), "");
93 | comment.Ip = entry.SelectSingleNode("AuthorIPAddress").InnerText;
94 | comment.Website = entry.SelectSingleNode("AuthorHomepage").InnerText;
95 | comment.Content = entry.SelectSingleNode("Content").InnerText;
96 | comment.PubDate = DateTime.Parse(ReadValue(entry.SelectSingleNode("Created"), ""));
97 | comment.ID = entry.SelectSingleNode("EntryId").InnerText;
98 | comment.UserAgent = ReadValue(entry.SelectSingleNode("AuthorUserAgent"), "");
99 |
100 | bool isOpenId = bool.Parse(ReadValue(entry.SelectSingleNode("OpenId"), "false"));
101 |
102 | if (isOpenId)
103 | {
104 | comment.Author = "n/a";
105 | }
106 |
107 | post.Comments.Add(comment);
108 |
109 | Storage.Save(post, postFile);
110 | }
111 | }
112 | }
113 |
114 | private static XmlDocument LoadDocument(string file)
115 | {
116 | string doc = File.ReadAllText(file).Replace(" xmlns=\"urn:newtelligence-com:dasblog:runtime:data\"", string.Empty);
117 |
118 | XmlDocument docOrig = new XmlDocument();
119 | docOrig.LoadXml(doc);
120 | return docOrig;
121 | }
122 |
123 | private static string ReadValue(XmlNode node, string defaultValue = "")
124 | {
125 | if (node != null)
126 | return node.InnerText;
127 |
128 | return defaultValue;
129 | }
130 |
131 | private string FormatSlug(XmlNode node)
132 | {
133 | return FormatterHelpers.FormatSlug(node.InnerText);
134 | }
135 |
136 | private IEnumerable FormatCategories(XmlNode catNode)
137 | {
138 | if (catNode == null || string.IsNullOrEmpty(catNode.InnerText))
139 | yield break;
140 |
141 | string[] categories = catNode.InnerText.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
142 |
143 | foreach (string category in categories)
144 | {
145 | yield return category;
146 | }
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/Formatters/FormatterHelpers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.RegularExpressions;
6 | using System.Threading.Tasks;
7 |
8 | namespace MiniBlogFormatter
9 | {
10 | public static class FormatterHelpers
11 | {
12 | public static string FormatSlug(string slug)
13 | {
14 | string text = slug.ToLowerInvariant().Replace(" ", "-");
15 | return Regex.Replace(text, @"([^0-9a-z-\(\)])", string.Empty).Trim();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/Formatters/GhostFormatter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.IO;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text.RegularExpressions;
7 | using MiniBlogFormatter.Models;
8 | using Newtonsoft.Json;
9 |
10 | namespace MiniBlogFormatter.Formatters
11 | {
12 | public class GhostFormatter
13 | {
14 | private readonly Regex imageRegex = new Regex(@"/content/images/", RegexOptions.Compiled);
15 |
16 | public void Format(string jsonFilePath, string targetFolderPath)
17 | {
18 | FormatPosts(jsonFilePath, targetFolderPath);
19 | }
20 |
21 | private void FormatPosts(string jsonFilePath, string targetFolderPath)
22 | {
23 | var rawJsonData = File.ReadAllText(jsonFilePath);
24 | var ghostData = JsonConvert.DeserializeObject(rawJsonData);
25 |
26 | foreach (var ghostPost in ghostData.data.posts)
27 | {
28 | var post = new Post
29 | {
30 | Categories = GetPostCategories(ghostData, ghostPost).ToArray(),
31 | Title = ghostPost.title,
32 | Slug = ghostPost.slug,
33 | PubDate = ghostPost.published_at.HasValue ? ConvertFromUnixEpoch(ghostPost.published_at.Value) : DateTime.Now,
34 | LastModified = ghostPost.updated_at.HasValue ? ConvertFromUnixEpoch(ghostPost.updated_at.Value) : DateTime.Now,
35 | Content = FormatFileReferences(ghostPost.html),
36 | Author = GetPostAuthor(ghostData, ghostPost),
37 | IsPublished = ghostPost.published_at.HasValue
38 | };
39 |
40 | var newFile = Path.Combine(targetFolderPath, ghostPost.uuid + ".xml");
41 | Storage.Save(post, newFile);
42 | }
43 | }
44 |
45 | private static DateTime ConvertFromUnixEpoch(long unixTime)
46 | {
47 | var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
48 |
49 | // We need to remove the last 3 digits of the unixtimeStamp otherwise it throws an overflow
50 | var timeStampString = unixTime.ToString(CultureInfo.CurrentCulture);
51 | timeStampString = timeStampString.Substring(0, timeStampString.Length - 3);
52 | var longTimestampFromString = long.Parse(timeStampString);
53 |
54 | return epoch.AddSeconds(longTimestampFromString);
55 | }
56 |
57 | private string FormatFileReferences(string content)
58 | {
59 | foreach (Match match in imageRegex.Matches(content))
60 | {
61 | content = content.Replace(match.Groups[0].Value, "/posts/files/" );
62 | }
63 |
64 | return content;
65 | }
66 |
67 | private static IEnumerable GetPostCategories(GhostData ghostData, GhostPost post)
68 | {
69 | var postCategoryIds = ghostData.data.posts_tags.Where(t => t.post_id == post.id).Select(c => c.tag_id).ToList();
70 | return postCategoryIds.Select(id => ghostData.data.tags.FirstOrDefault(t => t.id == id).name).ToArray();
71 | }
72 |
73 | private static string GetPostAuthor(GhostData ghostData, GhostPost post)
74 | {
75 | return ghostData.data.users.FirstOrDefault(u => u.id == post.created_by).name;
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/Formatters/WordpressFormatter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Text.RegularExpressions;
5 | using System.Xml;
6 | using System.Linq;
7 |
8 |
9 | namespace MiniBlogFormatter
10 | {
11 | public class WordpressFormatter
12 | {
13 | private Regex rxFiles = new Regex("(href|src)=\"(([^\"]+)(/content/binary/)([^\"]+))\"", RegexOptions.IgnoreCase);
14 |
15 | public void Format(string originalFolderPath, string targetFolderPath)
16 | {
17 | FormatPosts(originalFolderPath, targetFolderPath);
18 | }
19 |
20 | private void FormatPosts(string originalFolderPath, string targetFolderPath)
21 | {
22 | foreach (string file in Directory.GetFiles(originalFolderPath, "*.xml"))
23 | {
24 | XmlDocument docOrig = LoadDocument(file);
25 | XmlNamespaceManager nsm = LoadNamespaceManager(docOrig);
26 | XmlNamespaceManager namespaceManager = new XmlNamespaceManager(docOrig.NameTable);
27 | namespaceManager.AddNamespace("content", docOrig.DocumentElement.GetNamespaceOfPrefix("content"));
28 | namespaceManager.AddNamespace("dc", docOrig.DocumentElement.GetNamespaceOfPrefix("dc"));
29 | namespaceManager.AddNamespace("wp", docOrig.DocumentElement.GetNamespaceOfPrefix("wp"));
30 |
31 |
32 | foreach (XmlNode entry in docOrig.SelectNodes("//item", nsm))
33 | {
34 | Post post = new Post();
35 | XmlNodeList categories = entry.SelectNodes("category[@domain='category']");
36 | List resultCategories = new List();
37 | foreach (XmlNode category in categories)
38 | {
39 | resultCategories.Add(category.InnerText);
40 | }
41 |
42 | post.Categories = resultCategories.ToArray();
43 | post.Title = entry.SelectSingleNode("title").InnerText;
44 | post.Slug = FormatterHelpers.FormatSlug(post.Title);
45 | post.PubDate = DateTime.Parse(entry.SelectSingleNode("pubDate").InnerText);
46 | post.LastModified = DateTime.Parse(entry.SelectSingleNode("pubDate").InnerText);
47 |
48 |
49 | post.Content = FormatFileReferences(entry.SelectSingleNode("content:encoded", namespaceManager).InnerText);
50 | post.Author = entry.SelectSingleNode("dc:creator", namespaceManager).InnerText;
51 | post.IsPublished = ReadValue(entry.SelectSingleNode("wp:status", namespaceManager), "publish") == "publish";
52 |
53 | // FormatComments()
54 | foreach (XmlNode comment in entry.SelectNodes("wp:comment", namespaceManager))
55 | {
56 | FomartComment(ref post, comment, namespaceManager);
57 | }
58 |
59 |
60 | string newFile = Path.Combine(targetFolderPath, entry.SelectSingleNode("wp:post_id", namespaceManager).InnerText + ".xml");
61 | Storage.Save(post, newFile);
62 | }
63 | }
64 | }
65 |
66 | private void FomartComment(ref Post post, XmlNode entry, XmlNamespaceManager namespaceManager)
67 | {
68 | Comment comment = new Comment();
69 | comment.Author = ReadValue(entry.SelectSingleNode("wp:comment_author", namespaceManager), "n/a");
70 | comment.Email = ReadValue(entry.SelectSingleNode("wp:comment_author_email", namespaceManager), "");
71 | comment.Ip = entry.SelectSingleNode("wp:comment_author_IP", namespaceManager).InnerText;
72 | comment.Website = entry.SelectSingleNode("wp:comment_author_url", namespaceManager).InnerText;
73 | comment.Content = entry.SelectSingleNode("wp:comment_content", namespaceManager).InnerText;
74 | comment.PubDate = DateTime.Parse(ReadValue(entry.SelectSingleNode("wp:comment_date", namespaceManager), ""));
75 | comment.ID = entry.SelectSingleNode("wp:comment_id", namespaceManager).InnerText;
76 | comment.UserAgent = "n/a";
77 | post.Comments.Add(comment);
78 | }
79 |
80 | private string FormatFileReferences(string content)
81 | {
82 | foreach (Match match in rxFiles.Matches(content))
83 | {
84 | content = content.Replace(match.Groups[2].Value, "/posts/files/" + match.Groups[5].Value);
85 | }
86 |
87 | return content;
88 | }
89 |
90 | private static XmlNamespaceManager LoadNamespaceManager(XmlDocument docOrig)
91 | {
92 | XmlNamespaceManager nsm = new XmlNamespaceManager(docOrig.NameTable);
93 | nsm.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
94 | nsm.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
95 | return nsm;
96 | }
97 |
98 | private static XmlDocument LoadDocument(string file)
99 | {
100 | string doc = File.ReadAllText(file).Replace(" xmlns=\"urn:newtelligence-com:dasblog:runtime:data\"", string.Empty);
101 |
102 | XmlDocument docOrig = new XmlDocument();
103 | docOrig.LoadXml(doc);
104 | return docOrig;
105 | }
106 |
107 | private static string ReadValue(XmlNode node, string defaultValue = "")
108 | {
109 | if (node != null)
110 | return node.InnerText;
111 |
112 | return defaultValue;
113 | }
114 |
115 | private string FormatSlug(XmlNode node)
116 | {
117 | return FormatterHelpers.FormatSlug(node.InnerText);
118 | }
119 |
120 | private IEnumerable FormatCategories(XmlNode catNode)
121 | {
122 | if (catNode == null || string.IsNullOrEmpty(catNode.InnerText))
123 | yield break;
124 |
125 | string[] categories = catNode.InnerText.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
126 |
127 | foreach (string category in categories)
128 | {
129 | yield return category;
130 | }
131 | }
132 |
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/MiniBlogFormatter.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B92EB6D7-8C50-481C-B68D-A7C04CAFF65C}
8 | Exe
9 | Properties
10 | MiniBlogFormatter
11 | MiniBlogFormatter
12 | v4.5.1
13 | 512
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | False
38 | ..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
76 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/Models/Comment.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | public class Comment
4 | {
5 | public Comment()
6 | {
7 | ID = Guid.NewGuid().ToString();
8 | PubDate = DateTime.UtcNow;
9 | }
10 |
11 | public string ID { get; set; }
12 | public string Author { get; set; }
13 | public string Email { get; set; }
14 | public string Website { get; set; }
15 | public string Content { get; set; }
16 | public DateTime PubDate { get; set; }
17 | public string Ip { get; set; }
18 | public string UserAgent { get; set; }
19 | public bool IsAdmin { get; set; }
20 | }
--------------------------------------------------------------------------------
/MiniBlogFormatter/Models/GhostData.cs:
--------------------------------------------------------------------------------
1 | namespace MiniBlogFormatter.Models
2 | {
3 | public class GhostData
4 | {
5 | public Meta meta { get; set; }
6 | public Data data { get; set; }
7 | }
8 |
9 | public class Meta
10 | {
11 | public long exported_on { get; set; }
12 | public string version { get; set; }
13 | }
14 |
15 | public class Data
16 | {
17 | public GhostPost[] posts { get; set; }
18 | public User[] users { get; set; }
19 | public Role[] roles { get; set; }
20 | public Roles_Users[] roles_users { get; set; }
21 | public Permission[] permissions { get; set; }
22 | public object[] permissions_users { get; set; }
23 | public Permissions_Roles[] permissions_roles { get; set; }
24 | public Setting[] settings { get; set; }
25 | public Tag[] tags { get; set; }
26 | public Posts_Tags[] posts_tags { get; set; }
27 | }
28 |
29 | public class GhostPost
30 | {
31 | public int id { get; set; }
32 | public string uuid { get; set; }
33 | public string title { get; set; }
34 | public string slug { get; set; }
35 | public string markdown { get; set; }
36 | public string html { get; set; }
37 | public object image { get; set; }
38 | public int featured { get; set; }
39 | public int page { get; set; }
40 | public string status { get; set; }
41 | public string language { get; set; }
42 | public object meta_title { get; set; }
43 | public object meta_description { get; set; }
44 | public int? author_id { get; set; }
45 | public long? created_at { get; set; }
46 | public int? created_by { get; set; }
47 | public long? updated_at { get; set; }
48 | public int? updated_by { get; set; }
49 | public long? published_at { get; set; }
50 | public int? published_by { get; set; }
51 | }
52 |
53 | public class User
54 | {
55 | public int id { get; set; }
56 | public string uuid { get; set; }
57 | public string name { get; set; }
58 | public string slug { get; set; }
59 | public string password { get; set; }
60 | public string email { get; set; }
61 | public object image { get; set; }
62 | public object cover { get; set; }
63 | public string bio { get; set; }
64 | public string website { get; set; }
65 | public string location { get; set; }
66 | public object accessibility { get; set; }
67 | public string status { get; set; }
68 | public string language { get; set; }
69 | public object meta_title { get; set; }
70 | public object meta_description { get; set; }
71 | public object last_login { get; set; }
72 | public long? created_at { get; set; }
73 | public int? created_by { get; set; }
74 | public long? updated_at { get; set; }
75 | public int? updated_by { get; set; }
76 | }
77 |
78 | public class Role
79 | {
80 | public int id { get; set; }
81 | public string uuid { get; set; }
82 | public string name { get; set; }
83 | public string description { get; set; }
84 | public long? created_at { get; set; }
85 | public int? created_by { get; set; }
86 | public long? updated_at { get; set; }
87 | public int? updated_by { get; set; }
88 | }
89 |
90 | public class Roles_Users
91 | {
92 | public int id { get; set; }
93 | public int? role_id { get; set; }
94 | public int? user_id { get; set; }
95 | }
96 |
97 | public class Permission
98 | {
99 | public int id { get; set; }
100 | public string uuid { get; set; }
101 | public string name { get; set; }
102 | public string object_type { get; set; }
103 | public string action_type { get; set; }
104 | public object object_id { get; set; }
105 | public long? created_at { get; set; }
106 | public int? created_by { get; set; }
107 | public long? updated_at { get; set; }
108 | public int? updated_by { get; set; }
109 | }
110 |
111 | public class Permissions_Roles
112 | {
113 | public int id { get; set; }
114 | public int? role_id { get; set; }
115 | public int? permission_id { get; set; }
116 | }
117 |
118 | public class Setting
119 | {
120 | public int id { get; set; }
121 | public string uuid { get; set; }
122 | public string key { get; set; }
123 | public string value { get; set; }
124 | public string type { get; set; }
125 | public long? created_at { get; set; }
126 | public int? created_by { get; set; }
127 | public long? updated_at { get; set; }
128 | public int? updated_by { get; set; }
129 | }
130 |
131 | public class Tag
132 | {
133 | public int id { get; set; }
134 | public string uuid { get; set; }
135 | public string name { get; set; }
136 | public string slug { get; set; }
137 | public object description { get; set; }
138 | public object parent_id { get; set; }
139 | public object meta_title { get; set; }
140 | public object meta_description { get; set; }
141 | public long? created_at { get; set; }
142 | public int? created_by { get; set; }
143 | public long? updated_at { get; set; }
144 | public int? updated_by { get; set; }
145 | }
146 |
147 | public class Posts_Tags
148 | {
149 | public int id { get; set; }
150 | public int? post_id { get; set; }
151 | public int? tag_id { get; set; }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/Models/Post.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Web;
4 |
5 | public class Post
6 | {
7 | public Post()
8 | {
9 | ID = Guid.NewGuid().ToString();
10 | Title = "My new post";
11 | Content = "the content";
12 | PubDate = DateTime.UtcNow;
13 | LastModified = DateTime.UtcNow;
14 | Categories = new string[0];
15 | Comments = new List();
16 | IsPublished = true;
17 | }
18 |
19 | public string ID { get; set; }
20 |
21 | public string Title { get; set; }
22 |
23 | public string Author { get; set; }
24 |
25 | public string Slug { get; set; }
26 |
27 | public string Content { get; set; }
28 |
29 | public DateTime PubDate { get; set; }
30 |
31 | public DateTime LastModified { get; set; }
32 |
33 | public bool IsPublished { get; set; }
34 |
35 | public string[] Categories { get; set; }
36 | public List Comments { get; set; }
37 | }
--------------------------------------------------------------------------------
/MiniBlogFormatter/Models/Storage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Web;
5 | using System.Xml.Linq;
6 | using System.Xml.XPath;
7 |
8 | public static class Storage
9 | {
10 | public static void Save(Post post, string file)
11 | {
12 | post.LastModified = DateTime.UtcNow;
13 |
14 | XDocument doc = new XDocument(
15 | new XElement("post",
16 | new XElement("title", post.Title),
17 | new XElement("slug", post.Slug),
18 | new XElement("author", post.Author),
19 | new XElement("pubDate", post.PubDate.ToString("yyyy-MM-dd HH:mm:ss")),
20 | new XElement("lastModified", post.LastModified.ToString("yyyy-MM-dd HH:mm:ss")),
21 | new XElement("content", post.Content),
22 | new XElement("ispublished", post.IsPublished),
23 | new XElement("categories", string.Empty),
24 | new XElement("comments", string.Empty)
25 | ));
26 |
27 | XElement categories = doc.XPathSelectElement("post/categories");
28 | foreach (string category in post.Categories)
29 | {
30 | categories.Add(new XElement("category", category));
31 | }
32 |
33 | XElement comments = doc.XPathSelectElement("post/comments");
34 | foreach (Comment comment in post.Comments)
35 | {
36 | comments.Add(
37 | new XElement("comment",
38 | new XElement("author", comment.Author),
39 | new XElement("email", comment.Email),
40 | new XElement("website", comment.Website),
41 | new XElement("ip", comment.Ip),
42 | new XElement("userAgent", comment.UserAgent),
43 | new XElement("date", comment.PubDate.ToString("yyyy-MM-dd HH:m:ss")),
44 | new XElement("content", comment.Content),
45 | new XAttribute("isAdmin", comment.IsAdmin),
46 | new XAttribute("id", comment.ID)
47 | ));
48 | }
49 |
50 | doc.Save(file);
51 | }
52 |
53 | public static Post LoadPost(string file)
54 | {
55 | XElement doc = XElement.Load(file);
56 |
57 | Post post = new Post()
58 | {
59 | ID = Path.GetFileNameWithoutExtension(file),
60 | Title = ReadValue(doc, "title"),
61 | Author = ReadValue(doc, "author"),
62 | Content = ReadValue(doc, "content"),
63 | Slug = ReadValue(doc, "slug").ToLowerInvariant(),
64 | PubDate = DateTime.Parse(ReadValue(doc, "pubDate")),
65 | LastModified = DateTime.Parse(ReadValue(doc, "lastModified", DateTime.Now.ToString())),
66 | IsPublished = bool.Parse(ReadValue(doc, "ispublished", "true")),
67 | };
68 |
69 | return post;
70 | }
71 |
72 | //private static void LoadCategories(Post post, XElement doc)
73 | //{
74 | // XElement categories = doc.Element("categories");
75 | // if (categories == null)
76 | // return;
77 |
78 | // List list = new List();
79 |
80 | // foreach (var node in categories.Elements("category"))
81 | // {
82 | // list.Add(node.Value);
83 | // }
84 |
85 | // post.Categories = list.ToArray();
86 | //}
87 | //private static void LoadComments(Post post, XElement doc)
88 | //{
89 | // var comments = doc.Element("comments");
90 |
91 | // if (comments == null)
92 | // return;
93 |
94 | // foreach (var node in comments.Elements("comment"))
95 | // {
96 | // Comment comment = new Comment()
97 | // {
98 | // ID = ReadAttribute(node, "id"),
99 | // Author = ReadValue(node, "author"),
100 | // Email = ReadValue(node, "email"),
101 | // Website = ReadValue(node, "website"),
102 | // Ip = ReadValue(node, "ip"),
103 | // UserAgent = ReadValue(node, "userAgent"),
104 | // IsAdmin = bool.Parse(ReadAttribute(node, "isAdmin", "false")),
105 | // Content = ReadValue(node, "content").Replace("\n", "
"),
106 | // PubDate = DateTime.Parse(ReadValue(node, "date", "2000-01-01")),
107 | // };
108 |
109 | // post.Comments.Add(comment);
110 | // }
111 | //}
112 |
113 | private static string ReadValue(XElement doc, XName name, string defaultValue = "")
114 | {
115 | if (doc.Element(name) != null)
116 | return doc.Element(name).Value;
117 |
118 | return defaultValue;
119 | }
120 |
121 | private static string ReadAttribute(XElement element, XName name, string defaultValue = "")
122 | {
123 | if (element.Attribute(name) != null)
124 | return element.Attribute(name).Value;
125 |
126 | return defaultValue;
127 | }
128 | }
--------------------------------------------------------------------------------
/MiniBlogFormatter/Program.cs:
--------------------------------------------------------------------------------
1 | using MiniBlogFormatter.Formatters;
2 | using System.IO;
3 |
4 | namespace MiniBlogFormatter
5 | {
6 | class Program
7 | {
8 | static void Main(string[] args)
9 | {
10 | // For BlogEngine.NET only
11 | var categories = @"C:\dev\MiniBlogFormatter\myblogposts";
12 |
13 | // For both BlogEngine.NET and DasBlog
14 | //var origin = @"C:\Temp\GhostData.json";
15 | //var destination = @"C:\Temp\Formatted";
16 |
17 |
18 | //BlogEngine(categories, folder, destination);
19 | //Wordpress(origin, destination);
20 |
21 | //Ghost(origin, destination);
22 |
23 | // For BlogML
24 | var base64File = @"C:\Blog\BlogMLExport-b64.xml";
25 | var origin = @"C:\dev\BlogMLExport.xml";
26 | var destination = @"C:\dev\formatted";
27 | BlogML(origin, destination, base64File);
28 | }
29 |
30 | static void BlogML(string file, string destination, string base64File = null)
31 | {
32 | var formatter = new BlogMLFormatter();
33 | if (base64File != null)
34 | {
35 | formatter.ConvertFromBase64(base64File, file);
36 | }
37 |
38 | formatter.Format(file, destination);
39 | }
40 |
41 | private static void DasBlog(string folder, string destination)
42 | {
43 | var formatter = new DasBlogFormatter();
44 | formatter.Format(folder, destination);
45 | }
46 |
47 | private static void Wordpress(string folder, string destination)
48 | {
49 | var formatter = new WordpressFormatter();
50 | formatter.Format(folder, destination);
51 | }
52 |
53 |
54 | private static void BlogEngine(string categories, string folder, string destination)
55 | {
56 | var formatter = new BlogEngineFormatter();
57 | foreach (string file in Directory.GetFiles(folder, "*.xml"))
58 | {
59 | formatter.Format(file, destination, categories);
60 | }
61 | }
62 |
63 | private static void Ghost(string folder, string destination)
64 | {
65 | var formatter = new GhostFormatter();
66 | formatter.Format(folder, destination);
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/MiniBlogFormatter/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | MiniBlogFormatter
2 | =================
3 |
4 | This is a console app for converting your existing blog to MiniBlog.
5 |
6 | Current platforms supported:
7 |
8 | * BlogEngine.NET
9 | * BlogML
10 | * DasBlog
11 | * Ghost
12 | * WordPress
13 |
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.6.0.6/Newtonsoft.Json.6.0.6.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/MiniBlogFormatter/c5f185f9641e5cdf6ef6a65588f9e13f08d0f2cc/packages/Newtonsoft.Json.6.0.6/Newtonsoft.Json.6.0.6.nupkg
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.6.0.6/lib/net20/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/MiniBlogFormatter/c5f185f9641e5cdf6ef6a65588f9e13f08d0f2cc/packages/Newtonsoft.Json.6.0.6/lib/net20/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.6.0.6/lib/net35/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/MiniBlogFormatter/c5f185f9641e5cdf6ef6a65588f9e13f08d0f2cc/packages/Newtonsoft.Json.6.0.6/lib/net35/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.6.0.6/lib/net40/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/MiniBlogFormatter/c5f185f9641e5cdf6ef6a65588f9e13f08d0f2cc/packages/Newtonsoft.Json.6.0.6/lib/net40/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.6.0.6/lib/net45/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/MiniBlogFormatter/c5f185f9641e5cdf6ef6a65588f9e13f08d0f2cc/packages/Newtonsoft.Json.6.0.6/lib/net45/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.6.0.6/lib/netcore45/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/MiniBlogFormatter/c5f185f9641e5cdf6ef6a65588f9e13f08d0f2cc/packages/Newtonsoft.Json.6.0.6/lib/netcore45/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.6.0.6/lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/MiniBlogFormatter/c5f185f9641e5cdf6ef6a65588f9e13f08d0f2cc/packages/Newtonsoft.Json.6.0.6/lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.6.0.6/lib/portable-net45+wp80+win8+wpa81+aspnetcore50/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madskristensen/MiniBlogFormatter/c5f185f9641e5cdf6ef6a65588f9e13f08d0f2cc/packages/Newtonsoft.Json.6.0.6/lib/portable-net45+wp80+win8+wpa81+aspnetcore50/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.6.0.6/tools/install.ps1:
--------------------------------------------------------------------------------
1 | param($installPath, $toolsPath, $package, $project)
2 |
3 | # open json.net splash page on package install
4 | # don't open if json.net is installed as a dependency
5 |
6 | try
7 | {
8 | $url = "http://james.newtonking.com/json"
9 | $dte2 = Get-Interface $dte ([EnvDTE80.DTE2])
10 |
11 | if ($dte2.ActiveWindow.Caption -eq "Package Manager Console")
12 | {
13 | # user is installing from VS NuGet console
14 | # get reference to the window, the console host and the input history
15 | # show webpage if "install-package newtonsoft.json" was last input
16 |
17 | $consoleWindow = $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow])
18 |
19 | $props = $consoleWindow.GetType().GetProperties([System.Reflection.BindingFlags]::Instance -bor `
20 | [System.Reflection.BindingFlags]::NonPublic)
21 |
22 | $prop = $props | ? { $_.Name -eq "ActiveHostInfo" } | select -first 1
23 | if ($prop -eq $null) { return }
24 |
25 | $hostInfo = $prop.GetValue($consoleWindow)
26 | if ($hostInfo -eq $null) { return }
27 |
28 | $history = $hostInfo.WpfConsole.InputHistory.History
29 |
30 | $lastCommand = $history | select -last 1
31 |
32 | if ($lastCommand)
33 | {
34 | $lastCommand = $lastCommand.Trim().ToLower()
35 | if ($lastCommand.StartsWith("install-package") -and $lastCommand.Contains("newtonsoft.json"))
36 | {
37 | $dte2.ItemOperations.Navigate($url) | Out-Null
38 | }
39 | }
40 | }
41 | else
42 | {
43 | # user is installing from VS NuGet dialog
44 | # get reference to the window, then smart output console provider
45 | # show webpage if messages in buffered console contains "installing...newtonsoft.json" in last operation
46 |
47 | $instanceField = [NuGet.Dialog.PackageManagerWindow].GetField("CurrentInstance", [System.Reflection.BindingFlags]::Static -bor `
48 | [System.Reflection.BindingFlags]::NonPublic)
49 | $consoleField = [NuGet.Dialog.PackageManagerWindow].GetField("_smartOutputConsoleProvider", [System.Reflection.BindingFlags]::Instance -bor `
50 | [System.Reflection.BindingFlags]::NonPublic)
51 | if ($instanceField -eq $null -or $consoleField -eq $null) { return }
52 |
53 | $instance = $instanceField.GetValue($null)
54 | if ($instance -eq $null) { return }
55 |
56 | $consoleProvider = $consoleField.GetValue($instance)
57 | if ($consoleProvider -eq $null) { return }
58 |
59 | $console = $consoleProvider.CreateOutputConsole($false)
60 |
61 | $messagesField = $console.GetType().GetField("_messages", [System.Reflection.BindingFlags]::Instance -bor `
62 | [System.Reflection.BindingFlags]::NonPublic)
63 | if ($messagesField -eq $null) { return }
64 |
65 | $messages = $messagesField.GetValue($console)
66 | if ($messages -eq $null) { return }
67 |
68 | $operations = $messages -split "=============================="
69 |
70 | $lastOperation = $operations | select -last 1
71 |
72 | if ($lastOperation)
73 | {
74 | $lastOperation = $lastOperation.ToLower()
75 |
76 | $lines = $lastOperation -split "`r`n"
77 |
78 | $installMatch = $lines | ? { $_.StartsWith("------- installing...newtonsoft.json ") } | select -first 1
79 |
80 | if ($installMatch)
81 | {
82 | $dte2.ItemOperations.Navigate($url) | Out-Null
83 | }
84 | }
85 | }
86 | }
87 | catch
88 | {
89 | # stop potential errors from bubbling up
90 | # worst case the splash page won't open
91 | }
92 |
93 | # yolo
--------------------------------------------------------------------------------