PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/MarkPad/DocumentSources/MarkpadDocumentBase.cs

https://github.com/bcott/DownmarkerWPF
C# | 165 lines | 118 code | 31 blank | 16 comment | 17 complexity | e4dd1ed97fd881d31632e06234ae9210 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text.RegularExpressions;
  8. using System.Threading.Tasks;
  9. using MarkPad.Infrastructure;
  10. using MarkPad.Plugins;
  11. namespace MarkPad.DocumentSources
  12. {
  13. public abstract class MarkpadDocumentBase : IMarkpadDocument
  14. {
  15. readonly List<FileReference> associatedFiles = new List<FileReference>();
  16. readonly IDocumentFactory documentFactory;
  17. protected readonly IFileSystem FileSystem;
  18. protected MarkpadDocumentBase(
  19. string title, string content,
  20. string saveLocation,
  21. IEnumerable<FileReference> associatedFiles,
  22. IDocumentFactory documentFactory,
  23. ISiteContext siteContext,
  24. IFileSystem fileSystem)
  25. {
  26. if (title == null) throw new ArgumentNullException("title");
  27. if (documentFactory == null) throw new ArgumentNullException("documentFactory");
  28. if (siteContext == null) throw new ArgumentNullException("siteContext");
  29. Title = title;
  30. MarkdownContent = content;
  31. SaveLocation = saveLocation;
  32. SiteContext = siteContext;
  33. FileSystem = fileSystem;
  34. this.documentFactory = documentFactory;
  35. this.associatedFiles.AddRange(associatedFiles);
  36. }
  37. public string Title { get; protected set; }
  38. public string MarkdownContent { get; set; }
  39. /// <summary>
  40. /// Represents the location of this document, it could be a file path, a blog name, or anything that describes where this document lives
  41. /// </summary>
  42. public string SaveLocation { get; protected set; }
  43. public virtual ISiteContext SiteContext { get; private set; }
  44. protected IDocumentFactory DocumentFactory
  45. {
  46. get { return documentFactory; }
  47. }
  48. public abstract Task<IMarkpadDocument> Save();
  49. public virtual Task<IMarkpadDocument> SaveAs()
  50. {
  51. return documentFactory.SaveDocumentAs(this);
  52. }
  53. public virtual Task<IMarkpadDocument> Publish()
  54. {
  55. return documentFactory.PublishDocument(null, this);
  56. }
  57. public abstract FileReference SaveImage(Bitmap bitmap);
  58. public IEnumerable<FileReference> AssociatedFiles { get { return associatedFiles; } }
  59. public void AddFile(FileReference fileReference)
  60. {
  61. associatedFiles.Add(fileReference);
  62. }
  63. public abstract string ConvertToAbsolutePaths(string htmlDocument);
  64. public abstract bool IsSameItem(ISiteItem siteItem);
  65. public event PropertyChangedEventHandler PropertyChanged;
  66. protected virtual void OnPropertyChanged(string propertyName)
  67. {
  68. var handler = PropertyChanged;
  69. if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
  70. }
  71. /// <summary>
  72. ///
  73. /// </summary>
  74. /// <param name="startName">The seeding name, this can be the document name, will always return a .png filename</param>
  75. /// <param name="directory"></param>
  76. /// <returns>Absolute path of the image file</returns>
  77. protected string GetFileNameBasedOnTitle(string startName, string directory)
  78. {
  79. if (!FileSystem.Directory.Exists(directory))
  80. FileSystem.Directory.CreateDirectory(directory);
  81. var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(startName);
  82. if (fileNameWithoutExtension == null)
  83. return null;
  84. var fileName = fileNameWithoutExtension
  85. .Replace(" ", string.Empty)
  86. .Replace(".", string.Empty);
  87. var count = 1;
  88. var imageFileName = fileName + ".png";
  89. while (FileSystem.File.Exists(Path.Combine(directory, imageFileName)))
  90. {
  91. imageFileName = string.Format("{0}{1}.png", fileName, count++);
  92. }
  93. return Path.Combine(directory, imageFileName);
  94. }
  95. protected string ConvertToAbsolutePaths(string htmlDocument, string basePath)
  96. {
  97. var matches = Regex.Matches(htmlDocument, "src=\"(?<url>(?<!http://).*?)\"", RegexOptions.IgnoreCase);
  98. foreach (Match match in matches)
  99. {
  100. var replace = match.Captures[0].Value;
  101. var url = match.Groups["url"].Value;
  102. if (url.StartsWith("http://"))
  103. continue;
  104. var filePath = Path.Combine(basePath, url.TrimStart('/', '\\'));
  105. if (!FileSystem.File.Exists(filePath))
  106. continue;
  107. var base64String = Convert.ToBase64String(FileSystem.File.ReadAllBytes(filePath));
  108. htmlDocument = htmlDocument.Replace(replace, string.Format("src=\"data:image/png;base64,{0}\"", base64String));
  109. }
  110. return htmlDocument;
  111. }
  112. /// <summary>
  113. ///
  114. /// </summary>
  115. /// <param name="basePath"></param>
  116. /// <param name="fromFile"></param>
  117. /// <param name="toFile"></param>
  118. /// <returns>The relative path from the fromFile toFile (including toFile filename)</returns>
  119. protected string ToRelativePath(string basePath, string fromFile, string toFile)
  120. {
  121. var filename = Path.GetFileName(toFile);
  122. var toFilePath = Path.GetDirectoryName(toFile);
  123. var upFrom = fromFile.Replace(basePath, string.Empty);
  124. var toRelativeDirectory = toFilePath.Replace(basePath.Trim('\\', '/'), string.Empty).TrimStart('\\', '/');
  125. var enumerable = upFrom
  126. .TrimStart('\\', '/') //Get rid of starting /
  127. .Where(c => c == '/' || c == '\\') // select each / or \
  128. .Select(c => "..") // turn each into a ..
  129. .Concat(new[] { toRelativeDirectory, filename }) // concat with the image filename
  130. .Where(s=>!string.IsNullOrEmpty(s)); //Remove empty parts
  131. return string.Join("\\", enumerable); //now we join with path separator giving relative path
  132. }
  133. }
  134. }