Browse files

Improved exception handling and readme

  • Loading branch information...
1 parent bf8951f commit 3965caeb223515672c3711d66556cc42a2453ca6 @tpetricek committed Sep 23, 2012
View
40 README.md
@@ -1,10 +1,48 @@
F# Formatting
=============
-Markdown parser written in F#.
+This project contains an F# implementation of Markdown parser and a
+library that formats F# code. The formatting includes colorization, but
+also generation of tooltips with types and other information similar to
+those displayed in Visual Studio when reading F# code. An example can be
+found on [F# snippets web site](http://wwww.fssnip.net).
**TODO:** More information will be added soon.
+Using the library
+-----------------
+
+The two parts (Markdown parser and F# code formatter) are separate libraries,
+but they can be easily combined together. The following script shows how to
+parse Markdown document and then iterate over all CodeBlock elements (source
+code samples), add formatting to them and then put them back into a document.
+
+ * [example script used at www.tryjoinads.org](https://github.com/tpetricek/TryJoinads/blob/master/tools/build.fsx)
+
+### Using the F# formatting
+
+To format F# code using the `FSharp.Formatting.dll` library, you need to reference
+the library, open necessary namespaces and then create an instance of formatting
+agent:
+
+ #r "FSharp.CodeFormat.dll"
+ open FSharp.CodeFormat
+
+ let fsharpCompiler = "..\\FSharp.Compiler.dll"
+ let asm = System.Reflection.Assembly.LoadFile(fsharpCompiler)
+ let formatAgent = CodeFormat.CreateAgent(asm)
+
+Then you can use the agent repeatedly (it loads the F# compiler, so it is wise to reuse
+the same instance) to format a snippet as follows:
+
+ // 'fsharpSource' contains the actual source code,
+ // the first argument specifies a file name (does not need
+ // to physically exist) and the last is compiler arguments
+ let snippets, errors = formatAgent.ParseSource("source.fsx", fsharpSource, "")
+
+ // This formats the snippets into HTML
+ let formatted = CodeFormat.FormatHtml(snippets, "ft", false, false)
+
Known issues
------------
View
31 src/FSharp.CodeFormat.Tests/FSharp.CodeFormat.Tests.fsproj
@@ -35,6 +35,27 @@
<PlatformTarget>x86</PlatformTarget>
<DocumentationFile>bin\Release\FSharp.CodeFormat.Tests.XML</DocumentationFile>
</PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <Tailcalls>false</Tailcalls>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>bin\Debug\FSharp.CodeFormat.Tests.XML</DocumentationFile>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <Tailcalls>true</Tailcalls>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>bin\Release\FSharp.CodeFormat.Tests.XML</DocumentationFile>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
<ItemGroup>
@@ -44,9 +65,6 @@
</None>
</ItemGroup>
<ItemGroup>
- <Reference Include="FSharp.CodeFormat">
- <HintPath>..\FSharp.CodeFormat\bin\Debug\FSharp.CodeFormat.dll</HintPath>
- </Reference>
<Reference Include="FSharp.Core">
<HintPath>..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\FSharp\2.0\Runtime\v4.0\FSharp.Core.dll</HintPath>
</Reference>
@@ -55,6 +73,13 @@
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\FSharp.CodeFormat\FSharp.CodeFormat.fsproj">
+ <Name>FSharp.CodeFormat</Name>
+ <Project>{341ebf32-d470-4c55-99e9-55f14f7ffbb1}</Project>
+ <Private>True</Private>
+ </ProjectReference>
+ </ItemGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
View
16 src/FSharp.CodeFormat/CodeFormatAgent.fs
@@ -264,16 +264,19 @@ type CodeFormatAgent(fsharpCompiler) =
let! request, (chnl:AsyncReplyChannel<_>) = agent.Receive()
try
let! res, errs = processSourceCode request
- chnl.Reply(res |> Array.ofList, errs)
+ chnl.Reply(Choice1Of2(res |> Array.ofList, errs))
with e ->
- printfn "Failed %A" e
+ chnl.Reply(Choice2Of2(new Exception(Utilities.formatException e, e)))
})
/// Parse the source code specified by 'source', assuming that it
/// is located in a specified 'file'. Optional arguments can be used
/// to give compiler command line options and preprocessor definitions
- member x.AsyncParseSource(file, source, ?options, ?defines) =
- agent.PostAndAsyncReply(fun chnl -> (file, source, options, defines), chnl)
+ member x.AsyncParseSource(file, source, ?options, ?defines) = async {
+ let! res = agent.PostAndAsyncReply(fun chnl -> (file, source, options, defines), chnl)
+ match res with
+ | Choice1Of2 res -> return res
+ | Choice2Of2 exn -> return raise exn }
/// Parse the source code specified by 'source', assuming that it
/// is located in a specified 'file'. Optional arguments can be used
@@ -286,4 +289,7 @@ type CodeFormatAgent(fsharpCompiler) =
/// is located in a specified 'file'. Optional arguments can be used
/// to give compiler command line options and preprocessor definitions
member x.ParseSource(file, source, ?options, ?defines) =
- agent.PostAndReply(fun chnl -> (file, source, options, defines), chnl)
+ let res = agent.PostAndReply(fun chnl -> (file, source, options, defines), chnl)
+ match res with
+ | Choice1Of2 res -> res
+ | Choice2Of2 exn -> raise exn
View
26 src/FSharp.CodeFormat/FSharp.CodeFormat.fsproj
@@ -19,12 +19,11 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
- <OutputPath>bin\Debug\</OutputPath>
+ <OutputPath>..\..\..\FSharp.Formatting\bin\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
- <DocumentationFile>
- </DocumentationFile>
+ <DocumentationFile>..\..\..\FSharp.Formatting\bin\FSharp.CodeFormat.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType>
@@ -36,6 +35,27 @@
<PlatformTarget>x86</PlatformTarget>
<DocumentationFile>bin\Release\FSharp.CodeFormat.XML</DocumentationFile>
</PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <Tailcalls>false</Tailcalls>
+ <OutputPath>..\..\..\FSharp.Formatting\bin\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>..\..\..\FSharp.Formatting\bin\FSharp.CodeFormat.xml</DocumentationFile>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <Tailcalls>true</Tailcalls>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>bin\Release\FSharp.CodeFormat.XML</DocumentationFile>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
<ItemGroup>
View
11 src/FSharp.CodeFormat/FSharpCompiler.fs
@@ -526,11 +526,12 @@ module SourceCodeServices =
// member GetSlotsCount : options : CheckOptions -> int
// member UntypedParseForSlot : slot:int * options : CheckOptions -> UntypedParseInfo
-module Utils =
+module Utilities =
open Reflection
- /// Format an exception as a readable string with all information
- /// (this also handles exceptions thrown by the F# language service)
+ /// When an exception occurs in the FSharp.Compiler.dll, we may use
+ /// various dynamic tricks to get the actual message from all the
+ /// wrapper types - this throws a readable exception
let formatException e =
let sb = new Text.StringBuilder()
let rec printe s (e:exn) =
@@ -539,11 +540,15 @@ module Utils =
if name = "Microsoft.FSharp.Compiler.ErrorLogger+Error" then
let (tup:obj) = e?Data0
Printf.bprintf sb "Compile error (%d): %s" tup?Item1 tup?Item2
+ elif name = "Microsoft.FSharp.Compiler.ErrorLogger+InternalError" then
+ Printf.bprintf sb "Internal Error message: %s" e?Data0
elif name = "Microsoft.FSharp.Compiler.ErrorLogger+ReportedError" then
let (inner:obj) = e?Data0
if inner = null then Printf.bprintf sb "Reported error is null"
else printe "Reported error" (inner?Value)
elif e.InnerException <> null then
printe "Inner exception" e.InnerException
+
printe "Exception" e
sb.ToString()
+
View
15 src/FSharp.CodeFormat/HtmlFormatting.fs
@@ -57,6 +57,8 @@ type FormattingContext =
{ AddLines : bool
GenerateErrors : bool
Writer : TextWriter
+ OpenTag : string
+ CloseTag : string
FormatTip : ToolTipSpans -> bool -> (ToolTipSpans -> string) -> string }
// --------------------------------------------------------------------------------------
@@ -148,7 +150,9 @@ let formatSnippets (ctx:FormattingContext) (snippets:Snippet[]) =
let ctx = { ctx with Writer = new StringWriter(mainStr) }
// Generate <pre> tag for the snippet
- ctx.Writer.WriteLine("<pre class=\"fssnip\">")
+ if String.IsNullOrEmpty(ctx.OpenTag) |> not then
+ ctx.Writer.WriteLine(ctx.OpenTag)
+
let numberLength = lines.Length.ToString().Length
let linesLength = lines.Length
// Print all lines of the snippet
@@ -164,16 +168,19 @@ let formatSnippets (ctx:FormattingContext) (snippets:Snippet[]) =
if not isLast then ctx.Writer.WriteLine() )
// Close the <pre> tag for this snippet
- ctx.Writer.WriteLine("</pre>")
+ if String.IsNullOrEmpty(ctx.CloseTag) |> not then
+ ctx.Writer.WriteLine(ctx.CloseTag)
+
ctx.Writer.Close()
yield title, mainStr.ToString() |]
/// Format snippets and return HTML for <pre> tags together
/// wtih HTML for ToolTips (to be added to the end of document)
-let format addLines addErrors prefix (snippets:Snippet[]) =
+let format addLines addErrors prefix openTag closeTag (snippets:Snippet[]) =
let tipf = ToolTipFormatter(prefix)
let ctx = { AddLines = addLines; GenerateErrors = addErrors
- Writer = null; FormatTip = tipf.FormatTip }
+ Writer = null; FormatTip = tipf.FormatTip
+ OpenTag = openTag; CloseTag = closeTag }
// Generate main HTML for snippets
let snippets = formatSnippets ctx snippets
View
13 src/FSharp.CodeFormat/Main.fs
@@ -34,11 +34,20 @@ type CodeFormat =
/// The parameters specify prefix for HTML tags, whether lines should
/// be added to outputs and whether errors should be printed.
static member FormatHtml(snippets, prefix, addLines, addErrors) =
- let snip, tip = Html.format addLines addErrors prefix snippets
+ CodeFormat.FormatHtml
+ ( snippets, prefix, "<pre class=\"fssnip\">",
+ "</pre>", addLines, addErrors )
+
+ /// Formats the snippets parsed using the CodeFormatAgent as HTML
+ /// The parameters specify prefix for HTML tags, whether lines should
+ /// be added to outputs and whether errors should be printed.
+ static member FormatHtml(snippets, prefix, openTag, closeTag, addLines, addErrors) =
+ let snip, tip = Html.format addLines addErrors prefix openTag closeTag snippets
let snip = [| for t, h in snip -> FormattedSnippet(t, h) |]
FormattedHtml(snip, tip)
/// Formats the snippets parsed using the CodeFormatAgent as HTML
/// using the specified ID prefix and default settings.
static member FormatHtml(snippets, prefix) =
- CodeFormat.FormatHtml(snippets, prefix, true, false)
+ CodeFormat.FormatHtml(snippets, prefix, true, false)
+
View
24 src/FSharp.Formatting.sln
@@ -9,26 +9,50 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.CodeFormat", "FSharp
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.CodeFormat.Tests", "FSharp.CodeFormat.Tests\FSharp.CodeFormat.Tests.fsproj", "{5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FSharpX", "FSharpX", "{9371E533-7F81-4F20-A409-1F146F0D91EC}"
+ ProjectSection(SolutionItems) = preProject
+ FSharpX\Collections.fs = FSharpX\Collections.fs
+ FSharpX\StringParsing.fs = FSharpX\StringParsing.fs
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C44C1C05-599A-40DD-9590-465EAB8960C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C44C1C05-599A-40DD-9590-465EAB8960C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C44C1C05-599A-40DD-9590-465EAB8960C5}.Debug|x86.ActiveCfg = Debug|x86
{C44C1C05-599A-40DD-9590-465EAB8960C5}.Debug|x86.Build.0 = Debug|x86
+ {C44C1C05-599A-40DD-9590-465EAB8960C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C44C1C05-599A-40DD-9590-465EAB8960C5}.Release|Any CPU.Build.0 = Release|Any CPU
{C44C1C05-599A-40DD-9590-465EAB8960C5}.Release|x86.ActiveCfg = Release|x86
{C44C1C05-599A-40DD-9590-465EAB8960C5}.Release|x86.Build.0 = Release|x86
+ {07DE4905-050C-4378-A039-F1EF7E1F309D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {07DE4905-050C-4378-A039-F1EF7E1F309D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07DE4905-050C-4378-A039-F1EF7E1F309D}.Debug|x86.ActiveCfg = Debug|x86
{07DE4905-050C-4378-A039-F1EF7E1F309D}.Debug|x86.Build.0 = Debug|x86
+ {07DE4905-050C-4378-A039-F1EF7E1F309D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {07DE4905-050C-4378-A039-F1EF7E1F309D}.Release|Any CPU.Build.0 = Release|Any CPU
{07DE4905-050C-4378-A039-F1EF7E1F309D}.Release|x86.ActiveCfg = Release|x86
{07DE4905-050C-4378-A039-F1EF7E1F309D}.Release|x86.Build.0 = Release|x86
+ {341EBF32-D470-4C55-99E9-55F14F7FFBB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {341EBF32-D470-4C55-99E9-55F14F7FFBB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{341EBF32-D470-4C55-99E9-55F14F7FFBB1}.Debug|x86.ActiveCfg = Debug|x86
{341EBF32-D470-4C55-99E9-55F14F7FFBB1}.Debug|x86.Build.0 = Debug|x86
+ {341EBF32-D470-4C55-99E9-55F14F7FFBB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {341EBF32-D470-4C55-99E9-55F14F7FFBB1}.Release|Any CPU.Build.0 = Release|Any CPU
{341EBF32-D470-4C55-99E9-55F14F7FFBB1}.Release|x86.ActiveCfg = Release|x86
{341EBF32-D470-4C55-99E9-55F14F7FFBB1}.Release|x86.Build.0 = Release|x86
+ {5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}.Debug|x86.ActiveCfg = Debug|x86
{5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}.Debug|x86.Build.0 = Debug|x86
+ {5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}.Release|Any CPU.Build.0 = Release|Any CPU
{5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}.Release|x86.ActiveCfg = Release|x86
{5DEBD769-D86E-4E14-ABF1-373CA91BFAA2}.Release|x86.Build.0 = Release|x86
EndGlobalSection
View
21 src/FSharp.Markdown.Tests/FSharp.Markdown.Tests.fsproj
@@ -34,6 +34,27 @@
<PlatformTarget>x86</PlatformTarget>
<DocumentationFile>bin\Release\FSharp.Markdown.Tests.XML</DocumentationFile>
</PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <Tailcalls>false</Tailcalls>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>bin\Debug\FSharp.Markdown.Tests.XML</DocumentationFile>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <Tailcalls>true</Tailcalls>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>bin\Release\FSharp.Markdown.Tests.XML</DocumentationFile>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core" />
View
33 src/FSharp.Markdown/FSharp.Markdown.fsproj
@@ -19,11 +19,11 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
- <OutputPath>bin\Debug\</OutputPath>
+ <OutputPath>..\..\..\FSharp.Formatting\bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
- <DocumentationFile>bin\Debug\FSharp.Markdown.XML</DocumentationFile>
+ <DocumentationFile>..\..\..\FSharp.Formatting\bin\FSharp.Markdown.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType>
@@ -35,6 +35,27 @@
<PlatformTarget>x86</PlatformTarget>
<DocumentationFile>bin\Release\FSharp.Markdown.XML</DocumentationFile>
</PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <Tailcalls>false</Tailcalls>
+ <OutputPath>..\..\..\FSharp.Formatting\bin\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>..\..\..\FSharp.Formatting\bin\FSharp.Markdown.xml</DocumentationFile>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <Tailcalls>true</Tailcalls>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>bin\Release\FSharp.Markdown.XML</DocumentationFile>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core" />
@@ -43,8 +64,12 @@
<Reference Include="System.Numerics" />
</ItemGroup>
<ItemGroup>
- <Compile Include="..\FSharpX\Collections.fs" />
- <Compile Include="..\FSharpX\StringParsing.fs" />
+ <Compile Include="..\FSharpX\Collections.fs">
+ <Link>Collections.fs</Link>
+ </Compile>
+ <Compile Include="..\FSharpX\StringParsing.fs">
+ <Link>StringParsing.fs</Link>
+ </Compile>
<Compile Include="Markdown.fs" />
<Compile Include="MarkdownParser.fs" />
<Compile Include="HtmlFormatting.fs" />

0 comments on commit 3965cae

Please sign in to comment.