Skip to content

Commit

Permalink
fix a lot of common-mark tests (variable number of single quotes and …
Browse files Browse the repository at this point in the history
…tilde support)
  • Loading branch information
matthid committed Dec 29, 2015
1 parent 0518e65 commit 8a8a929
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 12 deletions.
18 changes: 16 additions & 2 deletions src/Common/StringParsing.fs
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,20 @@ module String =
/// The matched string is trimmed from all whitespace.
let (|StartsWithTrim|_|) (start:string) (text:string) =
if text.StartsWith(start) then Some(text.Substring(start.Length).Trim()) else None

/// Matches when a string starts with the specified sub-string (ignoring whitespace at the start)
/// The matched string is trimmed from all whitespace.
let (|StartsWithTrimIgnoreStartWhitespace|_|) (start:string) (text:string) =
let (|StartsWithNTimesTrimIgnoreStartWhitespace|_|) (start:string) (text:string) =
if text.Contains(start) then
let beforeStart = text.Substring(0, text.IndexOf(start))
if String.IsNullOrWhiteSpace (beforeStart) then
Some(beforeStart.Length, text.Substring(beforeStart.Length + start.Length).Trim())
let startAndRest = text.Substring(beforeStart.Length)
let startNum =
Seq.windowed start.Length startAndRest
|> Seq.map (fun chars -> System.String(chars))
|> Seq.takeWhile ((=) start)
|> Seq.length
Some(startNum, beforeStart.Length, text.Substring(beforeStart.Length + (start.Length * startNum)).Trim())
else None
else None

Expand Down Expand Up @@ -161,6 +168,13 @@ module List =
/// using the specified delimiter. Returns a wrapped list and the rest.
let inline (|Delimited|_|) str = (|DelimitedWith|_|) str str

let inline (|DelimitedNTimes|_|) str input =
let strs, items = List.partitionWhile (fun i -> i = str) input
match strs with
| h :: _ ->
(|Delimited|_|) (List.init strs.Length (fun _ -> str)) input
| _ -> None

/// Matches a list if it starts with a bracketed list. Nested brackets
/// are skipped (by counting opening and closing brackets) and can be
/// escaped using the '\' symbol.
Expand Down
2 changes: 1 addition & 1 deletion src/FSharp.Markdown/HtmlFormatting.fs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ let rec formatParagraph (ctx:FormattingContext) paragraph =
| CodeBlock(code, codeLanguage, _) ->
if ctx.WrapCodeSnippets then ctx.Writer.Write("<table class=\"pre\"><tr><td>")
let langCode = sprintf "language-%s" codeLanguage
ctx.Writer.Write(sprintf "<pre class=\"line-numbers %s\"><code class=\"%s\">" langCode langCode)
ctx.Writer.Write(sprintf "<pre><code class=\"%s\">" langCode)
ctx.Writer.Write(htmlEncode code)
ctx.Writer.Write("</code></pre>")
if ctx.WrapCodeSnippets then ctx.Writer.Write("</td></tr></table>")
Expand Down
30 changes: 21 additions & 9 deletions src/FSharp.Markdown/MarkdownParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,7 @@ let rec parseChars acc input = seq {
// Inline code delimited either using double `` or single `
// (if there are spaces around, then body can contain more backticks)
| List.DelimitedWith ['`'; ' '] [' '; '`'] (body, rest)
| List.Delimited ['`'; '`'] (body, rest)
| List.Delimited ['`'] (body, rest) ->
| List.DelimitedNTimes '`' (body, rest) ->
yield! accLiterals.Value
yield InlineCode(String(Array.ofList body).Trim())
yield! parseChars [] rest
Expand Down Expand Up @@ -300,10 +299,23 @@ let (|NestedCodeBlock|_|) = function
Some(code @ [""], rest, "", "")
| _ -> None

/// Recognizes a fenced code block - starting and ending with ```
/// Recognizes a fenced code block - starting and ending with at least ``` or ~~~
let (|FencedCodeBlock|_|) = function
| String.StartsWithTrimIgnoreStartWhitespace "```" (indent, header) :: lines ->
let code, rest = lines |> List.partitionUntil (fun line -> line.Contains "```")
| String.StartsWithNTimesTrimIgnoreStartWhitespace "~" (Let "~" (start,num), indent, header) :: lines
// when num > 2
| String.StartsWithNTimesTrimIgnoreStartWhitespace "`" (Let "`" (start,num), indent, header) :: lines
when num > 2 ->
let mutable endStr = String.replicate num start
if header.Contains (start) then None // info string cannot contain backspaces
else
let code, rest = lines |> List.partitionUntil (fun line ->
match [line] with
// end cannot contain info string afterwards (see http://spec.commonmark.org/0.23/#example-104)
// end must be indended with less then 4 spaces: http://spec.commonmark.org/0.23/#example-95
| String.StartsWithNTimesTrimIgnoreStartWhitespace start (n, i, h) :: _ when n >= num && i < 4 && not (h.Contains start) ->
endStr <- String.replicate n start
true
| _ -> false)
let handleIndent (l:string) =
if l.Length <= indent && String.IsNullOrWhiteSpace l then ""
elif l.Length > indent && String.IsNullOrWhiteSpace (l.Substring(0, indent)) then l.Substring(indent, l.Length - indent)
Expand All @@ -324,11 +336,11 @@ let (|FencedCodeBlock|_|) = function
let code, rest =
match rest with
| hd :: tl ->
let idx = hd.IndexOf("```")
if idx > -1 && idx + 3 <= hd.Length then
let idx = hd.IndexOf(endStr)
if idx > -1 && idx + endStr.Length <= hd.Length then
let pre = hd.Substring(0, idx)
let after = hd.Substring(idx + 3)
code @ [handleIndent pre], (if String.IsNullOrWhiteSpace after then tl else after :: tl)
let after = hd.Substring(idx + endStr.Length)
code @ [""], (if String.IsNullOrWhiteSpace after then tl else after :: tl)
else
code, tl
| _ ->
Expand Down

0 comments on commit 8a8a929

Please sign in to comment.