From 64b066f3fecd13b262c53bf789988fd61c29a359 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Fri, 10 Feb 2023 12:47:08 +0100 Subject: [PATCH] use Giraffe.ViewEngine for rendering html --- .../CSharpLayer/GenericChartExtensions.fs | 12 +- src/Plotly.NET/ChartAPI/Chart.fs | 74 +---- src/Plotly.NET/ChartAPI/GenericChart.fs | 296 +++++------------- .../DisplayOptions/DisplayOptions.fs | 94 ++---- src/Plotly.NET/Globals.fs | 29 ++ src/Plotly.NET/Plotly.NET.fsproj | 2 + src/Plotly.NET/Templates/Defaults.fs | 4 +- .../Plotly.NET.Tests.FSharpConsole/Program.fs | 17 +- .../HtmlCodegen/ChartLayout.fs | 39 ++- .../HtmlCodegen/SimpleTests.fs | 14 +- 10 files changed, 201 insertions(+), 380 deletions(-) create mode 100644 src/Plotly.NET/Globals.fs diff --git a/src/Plotly.NET/CSharpLayer/GenericChartExtensions.fs b/src/Plotly.NET/CSharpLayer/GenericChartExtensions.fs index 2d1314845..91fa36c52 100644 --- a/src/Plotly.NET/CSharpLayer/GenericChartExtensions.fs +++ b/src/Plotly.NET/CSharpLayer/GenericChartExtensions.fs @@ -4,6 +4,7 @@ open Plotly.NET.LayoutObjects open Plotly.NET.TraceObjects open System open System.IO +open Giraffe.ViewEngine open DynamicObj open GenericChart @@ -941,19 +942,19 @@ module GenericChartExtensions = /// Show chart in browser [] [] - member this.WithDescription(description: ChartDescription) = + member this.WithDescription(description: XmlNode list) = this |> Chart.withDescription description /// Adds the given additional script tags on the chart's DisplayOptions. They will be included in the document's [] [] - member this.WithAdditionalHeadTags(additionalHeadTags: seq) = + member this.WithAdditionalHeadTags(additionalHeadTags: XmlNode list) = this |> Chart.withAdditionalHeadTags additionalHeadTags /// Sets the given additional script tags on the chart's DisplayOptions. They will be included in the document's [] [] - member this.WithHeadTags(headTags: seq) = this |> Chart.withHeadTags headTags + member this.WithHeadTags(headTags: XmlNode list) = this |> Chart.withHeadTags headTags /// Adds the necessary script tags to render tex strings to the chart's DisplayOptions [] @@ -979,11 +980,6 @@ module GenericChartExtensions = [] member this.Show() = this |> Chart.show - /// Show chart in browser - [] - [] - member this.ShowAsImage(format: StyleParam.ImageFormat) = this |> Chart.showAsImage format - /// Sets the polar object with the given id on the chart layout [] member this.WithPolar(polar: Polar, [] ?Id) = diff --git a/src/Plotly.NET/ChartAPI/Chart.fs b/src/Plotly.NET/ChartAPI/Chart.fs index 9f2de8d2d..9dec96a15 100644 --- a/src/Plotly.NET/ChartAPI/Chart.fs +++ b/src/Plotly.NET/ChartAPI/Chart.fs @@ -7,7 +7,7 @@ open Plotly.NET.ConfigObjects open DynamicObj open System open System.IO - +open Giraffe.ViewEngine open GenericChart open System.Runtime.InteropServices @@ -52,33 +52,6 @@ type Chart = let path = Path.Combine(tempPath, file) ch |> Chart.saveHtml (path, true) - /// - /// Saves the given chart as a temporary html file containing a static image of the chart and opens it in the browser. - /// - /// IMPORTANT: this is not the same as static image generation. The file still needs to be opened in the browser to generate the image, as it is done via a js script in the html. - /// - /// For real programmatic static image export use Plotly.NET.ImageExport (https://www.nuget.org/packages/Plotly.NET.ImageExport/) - /// - /// This yields basically the same results as using `StaticPlot = true` for the chart's config. - /// - /// The image format for the static chart - /// The chart to show in the browser - [] - [] - static member showAsImage (format: StyleParam.ImageFormat) (ch: GenericChart) = - let guid = Guid.NewGuid().ToString() - let tempPath = Path.GetTempPath() - let file = sprintf "%s.html" guid - let path = Path.Combine(tempPath, file) - - let html = - ch - |> Chart.withAdditionalHeadTags [ """""" ] - |> GenericChart.toEmbeddedImage format - - File.WriteAllText(path, html) - path |> openOsSpecificFile - // ####################### /// Create a combined chart with the given charts merged [] @@ -3214,33 +3187,20 @@ type Chart = /// Show chart in browser [] - static member withDescription (description: ChartDescription) (ch: GenericChart) = - ch |> mapDisplayOptions (DisplayOptions.style (Description = description)) + static member withDescription (description: XmlNode list) (ch: GenericChart) = + ch |> mapDisplayOptions (DisplayOptions.addDescription description) + /// Adds the given additional html tags on the chart's DisplayOptions. They will be included in the document's [] - static member withAdditionalHeadTags (additionalHeadTags: seq) (ch: GenericChart) = - ch - |> mapDisplayOptions (fun d -> - let tags = - d.TryGetTypedValue>("AdditionalHeadTags") - - let newTags = - tags - |> Option.map (fun tags -> - seq { - yield! tags - yield! additionalHeadTags - }) - |> Option.defaultValue additionalHeadTags - - d |> DisplayOptions.style (AdditionalHeadTags = newTags)) + static member withAdditionalHeadTags (additionalHeadTags: XmlNode list) (ch: GenericChart) = + ch |> mapDisplayOptions (DisplayOptions.addAdditionalHeadTags additionalHeadTags) /// Sets the given additional head tags on the chart's DisplayOptions. They will be included in the document's [] - static member withHeadTags (headTags: seq) (ch: GenericChart) = - ch |> mapDisplayOptions (DisplayOptions.style (AdditionalHeadTags = headTags)) + static member withHeadTags (headTags: XmlNode list) (ch: GenericChart) = + ch |> mapDisplayOptions (fun d -> {d with AdditionalHeadTags = headTags}) /// Adds the necessary script tags to render tex strings to the chart's DisplayOptions @@ -3253,24 +3213,22 @@ type Chart = let tags = if version = 2 then - [ - """""" - """""" - ] + Globals.MATHJAX_V2_TAGS else - [ - """""" - """""" - ] + Globals.MATHJAX_V3_TAGS (fun (ch: GenericChart) -> if (AppendTags |> Option.defaultValue true) then ch |> Chart.withAdditionalHeadTags tags - |> Chart.withConfigStyle() + |> Chart.withConfigStyle(TypesetMath=true) else - ch |> Chart.withHeadTags tags) + ch + |> Chart.withHeadTags tags + |> Chart.withConfigStyle(TypesetMath=true) + ) + /// Sets the color axis with the given id on the chart layout [] diff --git a/src/Plotly.NET/ChartAPI/GenericChart.fs b/src/Plotly.NET/ChartAPI/GenericChart.fs index 3c36779de..2e0d9a817 100644 --- a/src/Plotly.NET/ChartAPI/GenericChart.fs +++ b/src/Plotly.NET/ChartAPI/GenericChart.fs @@ -4,121 +4,63 @@ open DynamicObj open System open Newtonsoft.Json open System.Runtime.CompilerServices - -/// HTML template for Plotly.js -module HTML = - - let doc = - """ - - - - - - - [ADDITIONAL_HEAD_TAGS] - - - - [CHART] - [DESCRIPTION] - -""" - - - let chart = - let newScript = - new System.Text.StringBuilder() - - newScript.AppendLine("""
""") |> ignore - newScript.AppendLine("") |> ignore - newScript.ToString() - - - let imageChart = - """ - - - - """ - + Plotly.newPlot('[ID]', data, layout, config); +}; +renderPlotly_[SCRIPTID](); +""" + let guid = Guid.NewGuid().ToString() + [ + div [_id guid] [comment "Plotly chart will be drawn inside this DIV"] + script [_type "text/javascript"] [ + rawText ( + scriptContent + .Replace("[SCRIPTID]",guid.Replace("-","")) + .Replace("[ID]",guid) + .Replace("[DATA]",data) + .Replace("[LAYOUT]",layout) + .Replace("[CONFIG]",config) + )] + ] + /// Module to represent a GenericChart [] module GenericChart = - - let internal jsonConfig = - JsonSerializerSettings() - - jsonConfig.ReferenceLoopHandling <- ReferenceLoopHandling.Serialize - type Figure = { [] @@ -150,9 +92,9 @@ module GenericChart = let layout = fig.Layout if traces.Length <> 1 then - MultiChart(traces, layout, Config(), DisplayOptions()) + MultiChart(traces, layout, Config(), DisplayOptions.Create()) else - Chart(traces.[0], layout, Config(), DisplayOptions()) + Chart(traces.[0], layout, Config(), DisplayOptions.Create()) let getTraces gChart = match gChart with @@ -292,12 +234,9 @@ module GenericChart = let combineDisplayOptions (first: DisplayOptions) (second: DisplayOptions) = - let additionalHeadTags = - combineOptSeqs - (first.TryGetTypedValue>("AdditionalHeadTags")) - (second.TryGetTypedValue>("AdditionalHeadTags")) - - DynObj.combine first second |> unbox |> DisplayOptions.style (?AdditionalHeadTags = additionalHeadTags) + first + |> DisplayOptions.addAdditionalHeadTags second.AdditionalHeadTags + |> DisplayOptions.addDescription second.Description gCharts |> Seq.reduce (fun acc elem -> @@ -336,119 +275,58 @@ module GenericChart = // let l' = layout |> List.rev // reduce l' (Layout()) - - /// Converts a GenericChart to it HTML representation. The div layer has a default size of 600 if not specified otherwise. let toChartHTML gChart = - let guid = Guid.NewGuid().ToString() - - let tracesJson = - let traces = getTraces gChart - JsonConvert.SerializeObject(traces, jsonConfig) - - let layoutJson = - let layout = getLayout gChart - JsonConvert.SerializeObject(layout, jsonConfig) - - let configJson = - let config = getConfig gChart - JsonConvert.SerializeObject(config, jsonConfig) - - let displayOpts = getDisplayOptions gChart - - let dims = tryGetLayoutSize gChart - - let width, height = - let w, h = tryGetLayoutSize gChart - w |> Option.defaultValue 600, h |> Option.defaultValue 600 - - - HTML - .chart - .Replace("[WIDTH]", string width) - .Replace("[HEIGHT]", string height) - .Replace("[ID]", guid) - .Replace("[SCRIPTID]", guid.Replace("-", "")) - .Replace("[DATA]", tracesJson) - .Replace("[LAYOUT]", layoutJson) - .Replace("[CONFIG]", configJson) - |> DisplayOptions.replaceHtmlPlaceholders displayOpts - - /// Converts a GenericChart to it HTML representation and set the size of the div - let toChartHtmlWithSize (width: int) (height: int) (gChart: GenericChart) = - let guid = Guid.NewGuid().ToString() - let tracesJson = let traces = getTraces gChart - JsonConvert.SerializeObject(traces, jsonConfig) + JsonConvert.SerializeObject(traces, Globals.JSON_CONFIG) let layoutJson = let layout = getLayout gChart - JsonConvert.SerializeObject(layout, jsonConfig) + JsonConvert.SerializeObject(layout, Globals.JSON_CONFIG) let configJson = let config = getConfig gChart - JsonConvert.SerializeObject(config, jsonConfig) + JsonConvert.SerializeObject(config, Globals.JSON_CONFIG) let displayOpts = getDisplayOptions gChart - HTML - .chart - .Replace("[ID]", guid) - .Replace("[WIDTH]", string width) - .Replace("[HEIGHT]", string height) - .Replace("[DATA]", tracesJson) - .Replace("[LAYOUT]", layoutJson) - .Replace("[CONFIG]", configJson) - |> DisplayOptions.replaceHtmlPlaceholders displayOpts + div [] [ + yield! HTML.CreateChartHTML( + tracesJson, + layoutJson, + configJson + ) + yield! displayOpts.Description + ] + |> RenderView.AsString.htmlNode /// Converts a GenericChart to it HTML representation and embeds it into a html page. let toEmbeddedHTML gChart = - let chartMarkup = toChartHTML gChart - - let displayOpts = getDisplayOptions gChart - - HTML.doc.Replace("[CHART]", chartMarkup) |> DisplayOptions.replaceHtmlPlaceholders displayOpts - - [] - let toChartImage (format: StyleParam.ImageFormat) gChart = - - let guid = Guid.NewGuid().ToString() - + let tracesJson = let traces = getTraces gChart - JsonConvert.SerializeObject(traces, jsonConfig) + JsonConvert.SerializeObject(traces, Globals.JSON_CONFIG) let layoutJson = let layout = getLayout gChart - JsonConvert.SerializeObject(layout, jsonConfig) - - let displayOpts = getDisplayOptions gChart - - HTML - .imageChart - .Replace("[WIDTH]", string 600) - .Replace("[HEIGHT]", string 600) - .Replace("[ID]", guid) - .Replace("[DATA]", tracesJson) - .Replace("[LAYOUT]", layoutJson) - .Replace("[IMAGEFORMAT]", format.ToString().ToLower()) - .Replace("[CONFIG]", "{}") - |> DisplayOptions.replaceHtmlPlaceholders displayOpts - - - /// Converts a GenericChart to an image and embeds it into a html page - let toEmbeddedImage (format: StyleParam.ImageFormat) gChart = + JsonConvert.SerializeObject(layout, Globals.JSON_CONFIG) - let chartMarkup = toChartImage format gChart + let configJson = + let config = getConfig gChart + JsonConvert.SerializeObject(config, Globals.JSON_CONFIG) let displayOpts = getDisplayOptions gChart - HTML - .doc - .Replace("[CHART]", chartMarkup) - .Replace("[CONFIG]", "{}") - |> DisplayOptions.replaceHtmlPlaceholders displayOpts - + HTML.Doc( + chart = HTML.CreateChartHTML( + tracesJson, + layoutJson, + configJson + ), + AdditionalHeadTags = displayOpts.AdditionalHeadTags, + Description = displayOpts.Description + ) + |> RenderView.AsString.htmlDocument /// Creates a new GenericChart whose traces are the results of applying the given function to each of the trace of the GenericChart. let mapTrace f gChart = @@ -484,8 +362,7 @@ module GenericChart = let defaultConfig = Config() Defaults.DefaultConfig.CopyDynamicPropertiesTo defaultConfig - let defaultDisplayOpts = DisplayOptions() - Defaults.DefaultDisplayOptions.CopyDynamicPropertiesTo defaultDisplayOpts + let defaultDisplayOpts = Defaults.DefaultDisplayOptions let defaultTemplate = Template() Defaults.DefaultTemplate.CopyDynamicPropertiesTo defaultTemplate @@ -501,7 +378,7 @@ module GenericChart = defaultDisplayOpts ) else - GenericChart.Chart(trace, Layout(), Config(), DisplayOptions()) + GenericChart.Chart(trace, Layout(), Config(), DisplayOptions.Create()) /// Converts from a list of trace objects and a layout object into GenericChart. If useDefaults = true, also sets the default Chart properties found in `Defaults` let ofTraceObjects (useDefaults: bool) traces = // layout = @@ -510,8 +387,7 @@ module GenericChart = let defaultConfig = Config() Defaults.DefaultConfig.CopyDynamicPropertiesTo defaultConfig - let defaultDisplayOpts = DisplayOptions() - Defaults.DefaultDisplayOptions.CopyDynamicPropertiesTo defaultDisplayOpts + let defaultDisplayOpts = Defaults.DefaultDisplayOptions let defaultTemplate = Template() Defaults.DefaultTemplate.CopyDynamicPropertiesTo defaultTemplate @@ -528,7 +404,7 @@ module GenericChart = ) else - GenericChart.MultiChart(traces, Layout(), Config(), DisplayOptions()) + GenericChart.MultiChart(traces, Layout(), Config(), DisplayOptions.Create()) /// let mapLayout f gChart = diff --git a/src/Plotly.NET/DisplayOptions/DisplayOptions.fs b/src/Plotly.NET/DisplayOptions/DisplayOptions.fs index 54c20dd94..df9a13910 100644 --- a/src/Plotly.NET/DisplayOptions/DisplayOptions.fs +++ b/src/Plotly.NET/DisplayOptions/DisplayOptions.fs @@ -2,71 +2,29 @@ open DynamicObj open System.Runtime.InteropServices - -type ChartDescription = - { - Heading: string - Text: string - } - - static member create heading text = { Heading = heading; Text = text } - - //to-do: when finally using a html dsl, adapt to return XMLNode - static member toHtml(d: ChartDescription) = - - let html = - """
-

[DESCRIPTIONHEADING]

-

[DESCRIPTIONTEXT]

-
""" - - html - .Replace("[DESCRIPTIONHEADING]", d.Heading) - .Replace("[DESCRIPTIONTEXT]", d.Text) - - -type DisplayOptions() = - inherit DynamicObj() - - static member init - ( - [] ?AdditionalHeadTags: seq, - [] ?Description: ChartDescription - ) = - DisplayOptions() |> DisplayOptions.style (?AdditionalHeadTags = AdditionalHeadTags, ?Description = Description) - - - // Applies the styles to Font() - static member style - ( - [] ?AdditionalHeadTags: seq, - [] ?Description: ChartDescription - ) = - (fun (displayOptions: DisplayOptions) -> - - AdditionalHeadTags |> DynObj.setValueOpt displayOptions "AdditionalHeadTags" - Description |> DynObj.setValueOpt displayOptions "Description" - - displayOptions) - - - static member getReplacements(displayOptions: DisplayOptions) = - [ - "[ADDITIONAL_HEAD_TAGS]", - (displayOptions.TryGetTypedValue>("AdditionalHeadTags") - |> Option.map (String.concat "\r\n") - |> Option.defaultValue "") - "[DESCRIPTION]", - (displayOptions.TryGetTypedValue("Description") - |> Option.map ChartDescription.toHtml - |> Option.defaultValue "") - ] - - static member replaceHtmlPlaceholders (displayOptions: DisplayOptions) (html: string) = - displayOptions - |> DisplayOptions.getReplacements - |> List.fold - (fun (html: string) (placeholder, replacement) -> - //printfn $"replacing {placeholder} {replacement}" - html.Replace(placeholder, replacement)) - html +open Giraffe.ViewEngine + +type DisplayOptions = { + AdditionalHeadTags: XmlNode list + Description: XmlNode list +} with + static member Create( + [] ?AdditionalHeadTags: XmlNode list, + [] ?Description: XmlNode list + ) = + { + AdditionalHeadTags = AdditionalHeadTags |> Option.defaultValue [] + Description = Description |> Option.defaultValue [] + } + + static member addAdditionalHeadTags (additionalHeadTags: XmlNode list) (displayOpts:DisplayOptions) = + { + displayOpts with + AdditionalHeadTags = List.append displayOpts.AdditionalHeadTags additionalHeadTags + } + + static member addDescription (description: XmlNode list) (displayOpts:DisplayOptions) = + { + displayOpts with + Description = List.append displayOpts.Description description + } diff --git a/src/Plotly.NET/Globals.fs b/src/Plotly.NET/Globals.fs new file mode 100644 index 000000000..ad1ca3534 --- /dev/null +++ b/src/Plotly.NET/Globals.fs @@ -0,0 +1,29 @@ +module Globals + +open DynamicObj +open System.Runtime.InteropServices +open Newtonsoft.Json +open Giraffe.ViewEngine + +/// The plotly js version loaded from cdn in rendered html docs +let [] PLOTLYJS_VERSION = "2.17.1" + +/// +let internal JSON_CONFIG = + JsonSerializerSettings( + ReferenceLoopHandling = ReferenceLoopHandling.Serialize + ) + +/// the mathjax v2 tags to add to html docs for rendering latex +let internal MATHJAX_V2_TAGS = + [ + script [_type "text/x-mathjax-config;executed=true"] [rawText """MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']], processEscapes: true}});"""] + script [_type "text/javascript"; _src """https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML%2CSafe.js&ver=4.1"""] [] + ] + +/// the mathjax v3 tags to add to html docs for rendering latex +let internal MATHJAX_V3_TAGS = + [ + script [] [rawText """MathJax = {tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]}};"""] + script [_src """https://cdn.jsdelivr.net/npm/mathjax@3.2.0/es5/tex-svg.js"""] [] + ] \ No newline at end of file diff --git a/src/Plotly.NET/Plotly.NET.fsproj b/src/Plotly.NET/Plotly.NET.fsproj index 9005e12b7..9b7c73580 100644 --- a/src/Plotly.NET/Plotly.NET.fsproj +++ b/src/Plotly.NET/Plotly.NET.fsproj @@ -36,6 +36,7 @@ + @@ -160,6 +161,7 @@ + diff --git a/src/Plotly.NET/Templates/Defaults.fs b/src/Plotly.NET/Templates/Defaults.fs index 173713606..be9ad2c26 100644 --- a/src/Plotly.NET/Templates/Defaults.fs +++ b/src/Plotly.NET/Templates/Defaults.fs @@ -25,7 +25,7 @@ module Defaults = /// The display options used for generating html. Default: DisplayOptions.init () let mutable DefaultDisplayOptions = - DisplayOptions.init () + DisplayOptions.Create() /// The default chart template. Default: ChartTemplates.plotly let mutable DefaultTemplate = @@ -36,5 +36,5 @@ module Defaults = DefaultWidth <- 600 DefaultHeight <- 600 DefaultConfig <- Config.init (Responsive = true) - DefaultDisplayOptions <- DisplayOptions.init () + DefaultDisplayOptions <- DisplayOptions.Create() DefaultTemplate <- ChartTemplates.plotly diff --git a/tests/Plotly.NET.Tests.FSharpConsole/Program.fs b/tests/Plotly.NET.Tests.FSharpConsole/Program.fs index 82ad3bcdd..7a1e7bd13 100644 --- a/tests/Plotly.NET.Tests.FSharpConsole/Program.fs +++ b/tests/Plotly.NET.Tests.FSharpConsole/Program.fs @@ -1,10 +1,12 @@ // Learn more about F# at http://docs.microsoft.com/dotnet/fsharp open System +open System.IO open Plotly.NET open Plotly.NET.LayoutObjects open Plotly.NET.TraceObjects open DynamicObj +open Giraffe.ViewEngine // Define a function to construct a message to print let from whom = @@ -19,8 +21,17 @@ let main argv = |> Chart.withAxisAnchor(Y=2) ] |> Chart.combine - //|> Chart.withYAxis(LinearAxis.init(),Id=StyleParam.SubPlotId.YAxis 1) - //|> Chart.withYAxis(LinearAxis.init(Shift = 10, Anchor = StyleParam.LinearAxisId.Free),Id=StyleParam.SubPlotId.YAxis 2) + |> Chart.withYAxis (LinearAxis.init(), Id = StyleParam.SubPlotId.YAxis 1) + |> Chart.withYAxis (LinearAxis.init(Anchor = StyleParam.LinearAxisId.Free, Shift = -50, ShowLine = true), Id = StyleParam.SubPlotId.YAxis 2) + |> Chart.withDescription [ + h1 [] [str "now look at this!"] + ul [] [ + li [] [str "this"] + li [] [str "is"] + li [] [str "a"] + li [] [img [_src "https://images.deepai.org/machine-learning-models/0c7ba850aa2443d7b40f9a45d9c86d3f/text2imgthumb.jpeg"]] + ] + ] + |> Chart.withSize(1000,1000) |> Chart.show - 0 \ No newline at end of file diff --git a/tests/Plotly.NET.Tests/HtmlCodegen/ChartLayout.fs b/tests/Plotly.NET.Tests/HtmlCodegen/ChartLayout.fs index ce489dd7f..b83894850 100644 --- a/tests/Plotly.NET.Tests/HtmlCodegen/ChartLayout.fs +++ b/tests/Plotly.NET.Tests/HtmlCodegen/ChartLayout.fs @@ -5,6 +5,7 @@ open Plotly.NET open Plotly.NET.LayoutObjects open Plotly.NET.TraceObjects open Plotly.NET.GenericChart +open Giraffe.ViewEngine open TestUtils.HtmlCodegen @@ -307,34 +308,32 @@ let ``Shapes`` = let displayOptionsChartDescriptionChart = let x = [1.; 2.; 3.; 4.; 5.; 6.; 7.; 8.; 9.; 10.; ] let y = [2.; 1.5; 5.; 1.5; 3.; 2.5; 2.5; 1.5; 3.5; 1.] - let description1 = ChartDescription.create "Hello" "F#" + let description1 = [ + h3 [] [str "Hello"] + p [] [str "F#"] + ] Chart.Point(x,y,Name="desc1", UseDefaults = false) |> Chart.withDescription(description1) let additionalHeadTagsChart = let x = [1.; 2.; 3.; 4.; 5.; 6.; 7.; 8.; 9.; 10.; ] let y = [2.; 1.5; 5.; 1.5; 3.; 2.5; 2.5; 1.5; 3.5; 1.] - let bulmaHero = """
-
-

- Hero title -

-

- Hero subtitle -

-
-
- """ - + let bulmaHero = + section [_class"hero is-primary is-bold"] [ + div [_class "hero-body"] [ + p [_class "title"] [str "Hero title"] + p [_class "subtitle"] [str "Hero subtitle"] + ] + ] // chart description containing bulma classes - let description3 = - ChartDescription.create - """

I am heading

""" - bulmaHero + let description3 = [ + h1 [_class "title"] [str "I am heading"] + bulmaHero + ] Chart.Point(x,y,Name="desc3", UseDefaults = false) |> Chart.withDescription description3 // Add reference to the bulma css framework - |> Chart.withAdditionalHeadTags [""""""] + |> Chart.withAdditionalHeadTags [link [_rel "stylesheet"; _href "https://cdn.jsdelivr.net/npm/bulma@0.9.2/css/bulma.min.css"]] let mathtexv3Chart = [ @@ -376,8 +375,8 @@ let ``Display options`` = |> substringIsInChart displayOptionsChartDescriptionChart toEmbeddedHTML ); testCase "Additional head tags" ( fun () -> - [ "

I am heading

" - "

" + [ "

I am heading

" + "
" "
" "

" "Hero title" diff --git a/tests/Plotly.NET.Tests/HtmlCodegen/SimpleTests.fs b/tests/Plotly.NET.Tests/HtmlCodegen/SimpleTests.fs index c329ef085..2927e1f4e 100644 --- a/tests/Plotly.NET.Tests/HtmlCodegen/SimpleTests.fs +++ b/tests/Plotly.NET.Tests/HtmlCodegen/SimpleTests.fs @@ -19,9 +19,9 @@ let simpleChart = [] let ``Html layout tests`` = testList "SimpleTests.Simple tests" [ - testCase "Expecting plotly js" ( fun () -> - "https://cdn.plot.ly/plotly-2.17.1.min" - |> chartGeneratedContains simpleChart + testCase "Expecting plotly js script reference in generated html document" ( fun () -> + $"""https://cdn.plot.ly/plotly-{Globals.PLOTLYJS_VERSION}.min""" + |> substringIsInChart simpleChart toEmbeddedHTML ); testCase "Expecting data" ( fun () -> """var data = [{"type":"scatter","mode":"markers","x":[0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"y":[0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0],"marker":{},"line":{}}];""" @@ -31,14 +31,6 @@ let ``Html layout tests`` = """var layout = {"title":{"text":"Hello world!"},"xaxis":{"title":{"text":"xAxis"},"showgrid":false},"yaxis":{"title":{"text":"yAxis"},"showgrid":false}};""" |> chartGeneratedContains simpleChart ); - testCase "Expecting cloudflare link" (fun () -> - "\"https://cdnjs.cloudflare.com/ajax/libs/require.js" - |> chartGeneratedContains simpleChart - ); - testCase "Expecting require config" (fun () -> - "var fsharpPlotlyRequire = requirejs.config({context:'fsharp-plotly',paths:{plotly:'https://cdn.plot.ly/plotly-2.17.1.min'}}) || require;" - |> chartGeneratedContains simpleChart - ); testCase "Expecting html tags in embedded page only" (fun () -> [""; ""; ""; ""; ""; ""; ""] |> substringListIsInChart simpleChart toEmbeddedHTML