) (eval: IEvaluator) = function
+ | Element(n, a, c) when prelude.ContainsKey n ->
+ prelude.[n] metadata a (c |> List.map (transform metadata prelude eval))
+ | Element(n, a, c) ->
+ Element(n, a, c |> List.map (transform metadata prelude eval))
+ | Expr(c, _) -> RawHtml (eval.Evaluate c)
| n -> n
module HtmlPrinter =
open Ast
-
+ let voidElements = [ "area"; "base"; "br"; "col"; "command"; "embed"; "hr"; "img"; "input"; "keygen"; "link"; "meta"; "param"; "source"; "track"; "wbr"]
+ let renderAttributes args =
+ args
+ |> List.map (fun m -> sprintf "%s=\"%s\"" (fst m) (snd m))
+ |> String.concat " "
let rec renderInline =
function
| Text t -> WebUtility.HtmlEncode t
| RawHtml h -> h
- | Element(t, a, c) -> sprintf "<%s>%s%s>" t (c |> List.map renderInline |> String.concat "") t
+ | Element(t,a,c) when List.contains t voidElements -> sprintf "<%s %s />" t (renderAttributes a)
+ | Element(t, a, c) -> sprintf "<%s %s>%s%s>" t (renderAttributes a) (c |> List.map renderInline |> String.concat "") t
| _ -> ""
let render (header, blocks) =
blocks
|> List.map (function
+ | Paragraph [RawHtml html] ->
+ html
+
+ // 2. (Frivillig) Mer robust guard om parsern råkar lämna kvar
+ // blanksteg (Text " ") runt ditt @md-block i samma paragraf
+ | Paragraph nodes when nodes |> List.forall (function
+ | RawHtml _ -> true
+ | Text t when System.String.IsNullOrWhiteSpace(t) -> true
+ | _ -> false) ->
+
+ nodes
+ |> List.choose (function RawHtml h -> Some h | _ -> None)
+ |> String.concat "\n"
| Paragraph c -> sprintf "%s
" (c |> List.map renderInline |> String.concat "")
| Section(l, _, c) -> sprintf "%s" l (c |> List.map renderInline |> String.concat "") l)
|> String.concat "\n"
@@ -427,49 +360,4 @@ module Evaluators =
Kritiskt FSI-systemfel: %s
""" ex.Message
- // interface IEvaluator with
- // member _.Evaluate(code: string) =
- // sbOut.Clear() |> ignore
- // sbErr.Clear() |> ignore
-
- // try
- // printfn "%s" code
-
- // // Kör koden i FSI
- // let result, _warnings = session.EvalInteractionNonThrowing code
-
- // // Läs av vad kompilatorn spottade ut
- // let output = sbOut.ToString().Trim()
- // let errors = sbErr.ToString().Trim()
-
- // match result with
- // | Choice1Of2 (Some fsiValue) ->
- // // Det gick bra och koden returnerade ett värde
- // let valStr = sprintf "%A" fsiValue.ReflectionValue
- // if System.String.IsNullOrEmpty(output) then valStr
- // else output + "\n" + valStr
-
- // | Choice1Of2 None ->
- // // Det gick bra, men koden returnerade inget värde (t.ex. en let-bindning)
- // // Om det fanns utskrifter i sbErr (t.ex. varningar), kan vi visa dem här:
- // if not (System.String.IsNullOrEmpty(errors)) then
- // output + sprintf "\n %A" errors
- // else
- // output
-
- // | Choice2Of2 ex ->
- // // FSI kastade ett exception (t.ex. syntaxfel eller runtime-fel)
- // let fsiErrorOutput = if System.String.IsNullOrEmpty(errors) then "Ingen ytterligare FSI-output." else errors
- // sprintf """
- //
- //
FSI Exekveringsfel!
- //
Kod som kördes: %s
- //
Exception: %s
- //
FSI Stderr: %s
- //
""" code ex.Message fsiErrorOutput
-
- // with ex ->
- // // Fångar upp om själva anropet till session.EvalInteractionNonThrowing kraschar helt
- // sprintf """
- // Kritiskt FSI-systemfel: %s
- //
""" ex.Message
+
diff --git a/src/FibLib/Pandoc.fs b/src/FibLib/Pandoc.fs
new file mode 100644
index 0000000..6b510e4
--- /dev/null
+++ b/src/FibLib/Pandoc.fs
@@ -0,0 +1,38 @@
+namespace Fibble.FibLib
+
+module Pandoc =
+ open System.Diagnostics
+
+ let toHtml (from: string) (markdownText: string) =
+ let startInfo = ProcessStartInfo(
+ FileName = "pandoc",
+ Arguments = $"-f {from} -t html5 --lua-filter strip-p.lua",
+ RedirectStandardInput = true,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true)
+
+ try
+ use proc = Process.Start startInfo
+ // Skriv markdown till Pandoc
+ use stdin = proc.StandardInput
+ stdin.Write markdownText
+ stdin.Close() // Måste stängas så Pandoc vet att texten är slut
+ // Läs ut resultatet
+ let htmlOutput = proc.StandardOutput.ReadToEnd()
+ let errorOutput = proc.StandardError.ReadToEnd()
+
+ proc.WaitForExit()
+
+ if proc.ExitCode = 0 then
+ htmlOutput.Trim()
+ else
+ sprintf "\n%s
and %s
" errorOutput markdownText
+
+ with ex ->
+ // Fångar upp om Pandoc inte är installerat eller inte finns i PATH
+ sprintf "\n%s
and %s
" ex.Message markdownText
+
+ let mdToHtml markdownText =
+ toHtml "markdown" markdownText
diff --git a/src/FibLib/strip-p.lua b/src/FibLib/strip-p.lua
new file mode 100644
index 0000000..3d7d3d7
--- /dev/null
+++ b/src/FibLib/strip-p.lua
@@ -0,0 +1,5 @@
+function Pandoc(doc)
+ if #doc.blocks > 0 and doc.blocks[1].t == "Para" then
+ return pandoc.Pandoc(doc.blocks[1].content, doc.meta)
+ end
+end
diff --git a/src/Fibble/Program.fs b/src/Fibble/Program.fs
index 3824277..f92e40c 100644
--- a/src/Fibble/Program.fs
+++ b/src/Fibble/Program.fs
@@ -7,41 +7,36 @@ open Fibble.FibLib.Ast // Ger oss tillgång till Element, Text, RawHtml etc.
// ==========================================
// makeElem returnerar nu en strukturerad Element-nod istället för en sträng
-let makeElem (name : string) =
- (name, fun args children -> Element(name, args, children))
+let elem (name : string) =
+ (name, fun meta args children -> Element(name, args, children))
let makeElems lst =
- List.map makeElem lst
+ List.map elem lst
-let defaultPrelude : Map =
- [ "b"; "em"; "i"; "strong" ]
- |> makeElems
- |> Map.ofList
-let myPrelude : Map =
- Map.ofList [
- "quotient", fun args _ ->
+let myPrelude : Map =
+ Map [
+ "quotient", fun _ args _ ->
if args.Length >= 2 then
Text (sprintf "%d" (int args.[0] / int args.[1]))
else
Text "[Fel: quotient kräver två argument]"
-
- "bold", fun args children ->
+ "bold", fun _ args children ->
Element("b", args, children)
-
- "link", fun args children ->
+ "value", fun meta args _ ->
+ Text meta[args.Head]
+ "link", fun _ args children ->
let url = if args.Length > 0 then args.[0].Trim('"') else "#"
- // Vi mappar argumenten till HTML-attribut (t.ex. href="...")
Element("a", [sprintf "href=\"%s\"" url], children)
-
+
// @br har varken argument eller barn, så vi returnerar bara rå HTML direkt
- "br", fun _ _ ->
- RawHtml "
"
- ]
+ "br", fun _ _ _ -> RawHtml "
"
+ ]
// ==========================================
// 2. Mall och Evaluator
// ==========================================
+
let pageTemplate = """
@@ -119,7 +114,7 @@ let increment () =
Första anropet: @(increment())
Andra anropet: @(increment())
-Test av utskrift:
+Test av utskrift: @value[date]
"
// ==========================================
// 3. Huvudpipeline
@@ -128,7 +123,7 @@ let processDocument (source: string) =
let evaluator = Evaluators.FsiEvaluator()
// Steg 1: Parsa koden
- let (metadata, rawBlocks) = Parser.parse source
+ let metadata, rawBlocks = Parser.parse source
// Hjälpfunktion: Gå igenom trädet och byt ut @value{...} mot faktiskt data från YAML
let rec resolveMeta = function
@@ -146,11 +141,11 @@ let processDocument (source: string) =
| Paragraph children ->
Paragraph (children
|> List.map resolveMeta
- |> List.map (Execution.transform myPrelude evaluator))
+ |> List.map (Execution.transform metadata myPrelude evaluator))
| Section(l, a, children) ->
Section(l, a, children
|> List.map resolveMeta
- |> List.map (Execution.transform myPrelude evaluator))
+ |> List.map (Execution.transform metadata myPrelude evaluator))
)
// Steg 3: Be printern skriva ut trädet till HTML