Skip to content

Commit

Permalink
Enable syntax highlighting for code in the Markdown Preview
Browse files Browse the repository at this point in the history
- Replaced MarkdownSharp with CommonMark.net given that it support natively fenced code blocks.
It also provide a more robust markdown specification that make markdown more predictable to write
and parse.
- Removed the setting that were used to customize MarkdownSharp behavior.
- Added the ability for the user to define a custom html template that is used to display the markdown preview.
Syntax highlighting can then be applied by using one of the many javascript libraries available on
the web.
Just include the required external dependecies (js,css, etc..) like one would have to do when
hosting the markdown in a normal webpage.
External resources can be pulled also directly from the web.
The code will look for an html file called WE-Markdown.html first in the project folder and
then in the solution folder. The same behavior has been extended to the WE-Markdown.css file.
Four custom place holder are provided:
  {##SOLUTION_PATH_PLACEHOLDER##}
  {##PROJECT_PATH_PLACEHOLDER##}
  {##DOCUMENT_PATH_PLACEHOLDER##}
  {##MARKDOWN_HTML_PLACEHOLDER##}
These placeholders can be used for instance to control where the external dependencies are pulled from.
The base element is set in the default template generated by the menu item to {##DOCUMENT_PATH_PLACEHOLDER##}.
This ensure the most confortable experience in VS, given that, for example, when an images is pasted or dragged into
a markdown document, the generated path to the image is relative to the markdown document itself.
- Added a menu to generate a default global solution html template (like the one for the custom stylesheet).
Note that the generated html does not include any reference to a javascript library to provide syntax highlighting.
The user will need to  choose one and modify the template accordingly.
- Added Code to try to automatically enable the internet features required to load and execute javascript in the
embedded WebBrowser.
A message will be printed in the visual studio output pane if something goes wrong.
  • Loading branch information
luca-piombino-deltatre committed Feb 1, 2015
1 parent c3d4ecc commit f328cee
Show file tree
Hide file tree
Showing 12 changed files with 687 additions and 103 deletions.
1 change: 1 addition & 0 deletions EditorExtensions/CommandConstants.cs
Expand Up @@ -114,6 +114,7 @@ enum CommandId
CreateMarkdownStylesheet = 0x1046,
CreateJavaScriptIntellisenseFile = 0x1047,
CreateTypeScriptIntellisenseFile = 0x1048,
CreateMarkdownHtmlTemplate = 0x1102,
MarkdownCompile = 0x1039,
HandlebarsCompile = 0x1101,
EditGlobalJsHint = 0x1038,
Expand Down
9 changes: 9 additions & 0 deletions EditorExtensions/EditorExtensions.vsct
Expand Up @@ -457,6 +457,14 @@
</Strings>
</Button>

<Button guid="guidDiffCmdSet" id="cmdMarkdownHtmlTemplate" priority="0x0107" type="Button">
<Parent guid="guidTopMenu" id="SolutionSubMenuGroup" />
<CommandFlag>DynamicVisibility</CommandFlag>
<Strings>
<ButtonText>Add Markdown solution html template</ButtonText>
</Strings>
</Button>

<Button guid="guidDiffCmdSet" id="cmdMarkdownCompile" priority="0x0102" type="Button">
<Parent guid="guidDiffCmdSet" id="MarkdownGroup" />
<CommandFlag>DynamicVisibility</CommandFlag>
Expand Down Expand Up @@ -943,6 +951,7 @@
<IDSymbol name="cmdMarkdownStylesheet" value="0x1046" />
<IDSymbol name="cmdJavaScriptIntellisense" value="0x1047" />
<IDSymbol name="cmdTypeScriptIntellisense" value="0x1048" />
<IDSymbol name="cmdMarkdownHtmlTemplate" value="0x1102" />
<IDSymbol name="MarkdownGroup" value="0x1049" />
<IDSymbol name="cmdEditGlobalJsHint" value="0x1038" />
<IDSymbol name="cmdEditGlobalTsLint" value="0x1098" />
Expand Down
685 changes: 642 additions & 43 deletions EditorExtensions/Markdown/Margin/MarkdownMargin.cs

Large diffs are not rendered by default.

20 changes: 19 additions & 1 deletion EditorExtensions/Markdown/MenuItems/Markdown.cs
Expand Up @@ -44,6 +44,11 @@ public void SetupCommands()
cssCommand.BeforeQueryStatus += HasStylesheet;
_mcs.AddCommand(cssCommand);

CommandID htmlTemplate = new CommandID(CommandGuids.guidDiffCmdSet, (int)CommandId.CreateMarkdownHtmlTemplate);
OleMenuCommand htmlTemplateCommand = new OleMenuCommand(async (s, e) => await AddHtmlTemplate(), htmlTemplate);
htmlTemplateCommand.BeforeQueryStatus += HasHtmlTemplate;
_mcs.AddCommand(htmlTemplateCommand);

CommandID compile = new CommandID(CommandGuids.guidDiffCmdSet, (int)CommandId.MarkdownCompile);
OleMenuCommand compileCommand = new OleMenuCommand((s, e) => AddHtmlFiles(), compile);
compileCommand.BeforeQueryStatus += IsMarkdownFile;
Expand All @@ -54,7 +59,15 @@ private void HasStylesheet(object sender, System.EventArgs e)
{
OleMenuCommand menuCommand = sender as OleMenuCommand;

menuCommand.Enabled = !File.Exists(MarkdownMargin.GetCustomStylesheetFilePath());
menuCommand.Enabled = !File.Exists(MarkdownMargin.GetCustomSolutionStylesheetFilePath());
}


private void HasHtmlTemplate(object sender, System.EventArgs e)
{
OleMenuCommand menuCommand = sender as OleMenuCommand;

menuCommand.Enabled = !File.Exists(MarkdownMargin.GetCustomSolutionHtmlTemplateFilePath());
}

private void IsMarkdownFile(object sender, System.EventArgs e)
Expand All @@ -78,5 +91,10 @@ private async static System.Threading.Tasks.Task AddStylesheet()
{
await MarkdownMargin.CreateStylesheet();
}

private async static System.Threading.Tasks.Task AddHtmlTemplate()
{
await MarkdownMargin.CreateHtmlTemplate();
}
}
}
7 changes: 0 additions & 7 deletions EditorExtensions/Settings/LegacySettings.cs
Expand Up @@ -58,13 +58,6 @@ public void ApplyTo(WESettings target)
target.Markdown.CompileOnSave = GetBoolean("MarkdownEnableCompiler");
target.Markdown.OutputDirectory = GetNonBooleanString("MarkdownCompileToLocation");

target.Markdown.AutoHyperlink = GetBoolean("MarkdownAutoHyperlinks");
target.Markdown.LinkEmails = GetBoolean("MarkdownLinkEmails");
target.Markdown.AutoNewLines = GetBoolean("MarkdownAutoNewLine");
target.Markdown.GenerateXHTML = GetBoolean("MarkdownGenerateXHTML");
target.Markdown.EncodeProblemUrlCharacters = GetBoolean("MarkdownEncodeProblemUrlCharacters");
target.Markdown.StrictBoldItalic = GetBoolean("MarkdownStrictBoldItalic");

// SVG
target.General.SvgPreviewPane = GetBoolean("SvgShowPreviewWindow");

Expand Down
46 changes: 5 additions & 41 deletions EditorExtensions/Settings/WESettings.cs
Expand Up @@ -3,7 +3,6 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using ConfOxide;
using MarkdownSharp;
using Microsoft.Ajax.Utilities;
using Microsoft.VisualStudio.Shell;
using WebMarkupMin.Core;
Expand Down Expand Up @@ -698,15 +697,16 @@ public sealed class HandlebarsSettings : SettingsBase<HandlebarsSettings>, IComp
public bool MinifyInPlace { get; set; }
}

public sealed class MarkdownSettings : SettingsBase<MarkdownSettings>, ICompilerInvocationSettings, IMarginSettings, IMarkdownOptions
public sealed class MarkdownSettings : SettingsBase<MarkdownSettings>, ICompilerInvocationSettings, IMarginSettings
{
#region Compilation
[Category("Editor")]
[DisplayName("Show preview pane")]
[Description("Show a preview pane containing the rendered output in the editor.")]
[DefaultValue(true)]
public bool ShowPreviewPane { get; set; }

#region Compilation

[Category("Compilation")]
[DisplayName("Compile files on save")]
[Description("Compile files when saving them, if a compiled file already exists.")]
Expand All @@ -723,50 +723,14 @@ public sealed class MarkdownSettings : SettingsBase<MarkdownSettings>, ICompiler
[Description("Specifies a custom subfolder to save compiled files to. By default, compiled output will be placed in the same folder and nested under the original file.")]
[DefaultValue(null)]
public string OutputDirectory { get; set; }
#endregion

[Category("Compile Options")]
[DisplayName("Make bare URLs into hyperlinks")]
[Description("When true, (most) bare plain Urls are auto-hyperlinked. WARNING: this is a significant deviation from the Markdown spec.")]
[DefaultValue(false)]
public bool AutoHyperlink { get; set; }

[Category("Compile Options")]
[DisplayName("Make bare emails into links")]
[Description("When false, email addresses will never be auto-linked. WARNING: this is a significant deviation from the Markdown spec.")]
[DefaultValue(false)]
public bool LinkEmails { get; set; }

[Category("Compile Options")]
[DisplayName("Make return into a newline")]
[Description("When true, RETURN becomes a literal newline. WARNING: this is a significant deviation from the Markdown spec.")]
[DefaultValue(false)]
public bool AutoNewLines { get; set; }

[Category("Compile Options")]
[DisplayName("Generate XHTML output")]
[Description("When true, the output is valid XHTML. Otherwise regular HTML it output. In this case, when true (mostly) means that single tags are closed with `/>` instead of `>`.")]
[DefaultValue(true)]
public bool GenerateXHTML { get; set; }

[Category("Compile Options")]
[DisplayName("Encode problem Url characters")]
[Description("When true, problematic Url characters like [, ], (, and so forth will be encoded. WARNING: this is a significant deviation from the Markdown spec.")]
[DefaultValue(false)]
public bool EncodeProblemUrlCharacters { get; set; }

[Category("Compile Options")]
[DisplayName("Require non-word characters for bold/italic")]
[Description("When true, bold and italic require non-word characters on both sides. WARNING: this is a significant deviation from the Markdown spec.")]
[DefaultValue(false)]
public bool StrictBoldItalic { get; set; }
string IMarkdownOptions.EmptyElementSuffix { get { return GenerateXHTML ? " />" : ">"; } }

[Category("Compilation")]
[DisplayName("Don't save raw compilation output")]
[Description("Don't save separate unminified compiler output. This option has no effect when Minify On Save is disabled for HTML.")]
[DefaultValue(false)]
public bool MinifyInPlace { get; set; }

#endregion
}

public interface IBundleSettings
Expand Down
7 changes: 6 additions & 1 deletion EditorExtensions/Shared/Compilers/CompilerRunner.cs
Expand Up @@ -255,7 +255,12 @@ class MarkdownCompilerRunner : CompilerRunnerBase

protected async override Task<CompilerResult> RunCompilerAsync(string sourcePath, string targetPath)
{
var result = new MarkdownSharp.Markdown(WESettings.Instance.Markdown).Transform(await FileHelpers.ReadAllTextRetry(sourcePath));
var sourceText = await FileHelpers.ReadAllTextRetry(sourcePath);
var settings = new CommonMark.CommonMarkSettings
{
OutputFormat = CommonMark.OutputFormat.Html
};
var result = CommonMark.CommonMarkConverter.Convert(sourceText, settings);

if (!string.IsNullOrEmpty(targetPath) &&
(!File.Exists(targetPath) || await FileHelpers.ReadAllTextRetry(targetPath) != result))
Expand Down
7 changes: 3 additions & 4 deletions EditorExtensions/WebEssentials2013.csproj
Expand Up @@ -101,6 +101,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\AjaxMin.5.12.5436.22734\lib\net40\AjaxMin.dll</HintPath>
</Reference>
<Reference Include="CommonMark">
<HintPath>..\packages\CommonMark.NET.0.5.2\lib\net45\CommonMark.dll</HintPath>
</Reference>
<Reference Include="ConfOxide, Version=1.4.0.0, Culture=neutral, PublicKeyToken=934faed64f82030e, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ConfOxide.1.4.0.0\lib\net40\ConfOxide.dll</HintPath>
Expand All @@ -121,10 +124,6 @@
<Reference Include="EnvDTE90, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<EmbedInteropTypes>False</EmbedInteropTypes>
</Reference>
<Reference Include="MarkdownSharp, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\MarkdownSharp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Collections.Immutable, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.JSON.Core">
Expand Down
1 change: 1 addition & 0 deletions EditorExtensions/packages.config
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AjaxMin" version="5.12.5436.22734" targetFramework="net451" />
<package id="CommonMark.NET" version="0.5.2" targetFramework="net451" />
<package id="ConfOxide" version="1.4.0.0" targetFramework="net451" />
<package id="Minimatch" version="1.1.0" targetFramework="net451" />
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net451" />
Expand Down
Binary file removed MarkdownSharp.dll
Binary file not shown.
3 changes: 1 addition & 2 deletions WebEssentials2013.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30501.0
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{140A15DE-0F66-4377-BB52-BC24C7FC46E9}"
ProjectSection(SolutionItems) = preProject
Expand All @@ -10,7 +10,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
CONTRIBUTING.md = CONTRIBUTING.md
CssSorter.dll = CssSorter.dll
LICENSE.txt = LICENSE.txt
MarkdownSharp.dll = MarkdownSharp.dll
README.md = README.md
Rebracer.xml = Rebracer.xml
WebEssentials2012logo.pdn = WebEssentials2012logo.pdn
Expand Down
4 changes: 0 additions & 4 deletions WebEssentialsTests/WebEssentialsTests.csproj
Expand Up @@ -55,10 +55,6 @@
<Reference Include="FluentAssertions.Core">
<HintPath>..\packages\FluentAssertions.3.0.107\lib\net45\FluentAssertions.Core.dll</HintPath>
</Reference>
<Reference Include="MarkdownSharp, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\MarkdownSharp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.CSS.Core, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.CSS.Editor, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
Expand Down

0 comments on commit f328cee

Please sign in to comment.