Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing Support for return md in latex functions. #905

Closed
schlichtanders opened this issue Oct 18, 2021 · 5 comments
Closed

Missing Support for return md in latex functions. #905

schlichtanders opened this issue Oct 18, 2021 · 5 comments

Comments

@schlichtanders
Copy link

I tried to return a simple md"myreturned value" however Franklin fails which is impossible to understand.

Take this slightly adapted example method

function lx_baz(com, _)
  # keep this first line
  brace_content = Franklin.content(com.braces[1]) # input string
  # do whatever you want here
  return md"$(uppercase(brace_content))"
end

and call it in your markdown like

\baz{Hello World}

then you get this

│ MethodError(Franklin.reprocess, ("HI"
│ , Franklin.LxDef[Franklin.LxDef{Pair{String, String}}("equation", 0, "\\[" => "\\]", -9223372036854774122, -9223372036854774119), Franklin.LxDef{Pair{String, String}}("align", 0, "\\[\\begin{aligned}" => "\\end{aligned}\\]", -9223372036854774117, -9223372036854774114), Franklin.LxDef{Pair{String, String}}("aligned", 0, "\\[\\begin{aligned}" => "\\end{aligned}\\]", -9223372036854774112, -9223372036854774109), Franklin.LxDef{Pair{String, String}}("eqnarray", 0, "\\[\\begin{array}{rcl}" => "\\end{array}\\]", -9223372036854774107, -9223372036854774104), Franklin.LxDef{SubString{String}}("\\eqref", 1, "", -9223372036854774102, -9223372036854774099), Franklin.LxDef{SubString{String}}("\\cite", 1, "", -9223372036854774097, -9223372036854774094), Franklin.LxDef{SubString{String}}("\\citet", 1, "", -9223372036854774092, -9223372036854774089), Franklin.LxDef{SubString{String}}("\\citep", 1, "", -9223372036854774087, -9223372036854774084), Franklin.LxDef{SubString{String}}("\\label", 1, "", -9223372036854774082, -9223372036854774079), Franklin.LxDef{SubString{String}}("\\biblabel", 2, "", -9223372036854774077, -9223372036854774074), Franklin.LxDef{SubString{String}}("\\toc", 0, "", -9223372036854774072, -9223372036854774069), Franklin.LxDef{SubString{String}}("\\reflink", 1, "", -9223372036854774067, -9223372036854774064), Franklin.LxDef{SubString{String}}("\\input", 2, "", -9223372036854774062, -9223372036854774059), Franklin.LxDef{SubString{String}}("\\output", 1, "", -9223372036854774057, -9223372036854774054), Franklin.LxDef{SubString{String}}("\\show", 1, "", -9223372036854774052, -9223372036854774049), Franklin.LxDef{SubString{String}}("\\textoutput", 1, "", -9223372036854774047, -9223372036854774044), Franklin.LxDef{SubString{String}}("\\textinput", 1, "", -9223372036854774042, -9223372036854774039), Franklin.LxDef{SubString{String}}("\\figalt", 2, "", -9223372036854774037, -9223372036854774034), Franklin.LxDef{SubString{String}}("\\tableinput", 2, "", -9223372036854774032, -9223372036854774029), Franklin.LxDef{SubString{String}}("\\literate", 1, "", -9223372036854774027, -9223372036854774024), Franklin.LxDef{SubString{String}}("\\fig", 1, "\\figalt{}{#1}", -9223372036854774022, -9223372036854774019), Franklin.LxDef{SubString{String}}("\\style", 2, "~~~<span style=\"!#1\">~~~!#2~~~</span>~~~", -9223372036854774017, -9223372036854774014), Franklin.LxDef{SubString{String}}("\\tableofcontents", 0, "\\toc", -9223372036854774012, -9223372036854774009), Franklin.LxDef{SubString{String}}("\\codeoutput", 1, "\\output{#1}", -9223372036854774007, -9223372036854774004), Franklin.LxDef{SubString{String}}("\\R", 0, "\\mathbb R", -9223372036854774002, -9223372036854773999), Franklin.LxDef{SubString{String}}("\\scal", 1, "\\langle #1 \\rangle", -9223372036854773997, -9223372036854773994)]), 0x00000000000073ba)
└
ERROR: MethodError: no method matching reprocess(::Markdown.MD, ::Vector{Franklin.LxDef})
Closest candidates are:
  reprocess(::Union{SubString{String}, String}, ::Vector{var"#s119"} where var"#s119"<:Franklin.LxDef; nostripp) at /home/ssahm/.julia/packages/Franklin/2KNQE/src/converter/latex/latex.jl:77
Stacktrace:
 [1] serve(fw::LiveServer.SimpleWatcher; host::String, port::Int64, dir::String, verbose::Bool, coreloopfun::Franklin.var"#235#238"{NamedTuple{(:other, :infra, :md, :html, :literate), NTuple{5, Dict{Pair{String, String}, Float64}}}}, preprocess_request::typeof(identity), inject_browser_reload_script::Bool, launch_browser::Bool, allow_cors::Bool)
   @ LiveServer ~/.julia/packages/LiveServer/ofHCn/src/server.jl:333
 [2] serve(; clear::Bool, verb::Bool, port::Int64, single::Bool, prerender::Bool, nomess::Bool, is_final_pass::Bool, no_fail_prerender::Bool, eval_all::Bool, silent::Bool, cleanup::Bool, on_write::Franklin.var"#236#239", log::Bool, host::String, show_warnings::Bool, fail_on_warning::Bool, launch::Bool, no_set_paths::Bool, join_to_prepath::String)
   @ Franklin ~/.julia/packages/Franklin/2KNQE/src/manager/franklin.jl:138
 [3] serve()
   @ Franklin ~/.julia/packages/Franklin/2KNQE/src/manager/franklin.jl:70
 [4] top-level scope
   @ none:1

caused by: MethodError: no method matching reprocess(::Markdown.MD, ::Vector{Franklin.LxDef})
Closest candidates are:
  reprocess(::Union{SubString{String}, String}, ::Vector{var"#s119"} where var"#s119"<:Franklin.LxDef; nostripp) at /home/ssahm/.julia/packages/Franklin/2KNQE/src/converter/latex/latex.jl:77
Stacktrace:
  [1] resolve_lxobj(lxo::Franklin.LxCom, lxdefs::Vector{Franklin.LxDef}; inmath::Bool)
    @ Franklin ~/.julia/packages/Franklin/2KNQE/src/converter/latex/latex.jl:39
  [2] resolve_lxobj
    @ ~/.julia/packages/Franklin/2KNQE/src/converter/latex/latex.jl:28 [inlined]
  [3] convert_block(β::Franklin.LxCom, lxdefs::Vector{Franklin.LxDef})
    @ Franklin ~/.julia/packages/Franklin/2KNQE/src/converter/markdown/blocks.jl:45
  [4] convert_inter_html(ihtml::String, blocks::Vector{Franklin.AbstractBlock}, lxdefs::Vector{Franklin.LxDef})
    @ Franklin ~/.julia/packages/Franklin/2KNQE/src/converter/markdown/md.jl:418
  [5] convert_md(mds::String, pre_lxdefs::Vector{Franklin.LxDef}; isrecursive::Bool, isinternal::Bool, isconfig::Bool, has_mddefs::Bool, pagevar::Bool, nostripp::Bool)
    @ Franklin ~/.julia/packages/Franklin/2KNQE/src/converter/markdown/md.jl:173
  [6] convert_md (repeats 2 times)
    @ ~/.julia/packages/Franklin/2KNQE/src/converter/markdown/md.jl:34 [inlined]
  [7] convert_and_write(root::String, file::String, head::String, pgfoot::String, foot::String, output_path::String)
    @ Franklin ~/.julia/packages/Franklin/2KNQE/src/manager/write_page.jl:175
  [8] process_file_err(case::Symbol, fpair::Pair{String, String}, head::String, pgfoot::String, foot::String, t::Float64)
    @ Franklin ~/.julia/packages/Franklin/2KNQE/src/manager/file_utils.jl:153
  [9] process_file(::Symbol, ::Pair{String, String}, ::String, ::Vararg{Any, N} where N)
    @ Franklin ~/.julia/packages/Franklin/2KNQE/src/manager/file_utils.jl:104
 [10] fd_loop(cycle_counter::Int64, #unused#::LiveServer.SimpleWatcher, watched_files::NamedTuple{(:other, :infra, :md, :html, :literate), NTuple{5, Dict{Pair{String, String}, Float64}}})
    @ Franklin ~/.julia/packages/Franklin/2KNQE/src/manager/franklin.jl:403
 [11] #235
    @ ~/.julia/packages/Franklin/2KNQE/src/manager/franklin.jl:134 [inlined]
 [12] serve(fw::LiveServer.SimpleWatcher; host::String, port::Int64, dir::String, verbose::Bool, coreloopfun::Franklin.var"#235#238"{NamedTuple{(:other, :infra, :md, :html, :literate), NTuple{5, Dict{Pair{String, String}, Float64}}}}, preprocess_request::typeof(identity), inject_browser_reload_script::Bool, launch_browser::Bool, allow_cors::Bool)
    @ LiveServer ~/.julia/packages/LiveServer/ofHCn/src/server.jl:326
 [13] serve(; clear::Bool, verb::Bool, port::Int64, single::Bool, prerender::Bool, nomess::Bool, is_final_pass::Bool, no_fail_prerender::Bool, eval_all::Bool, silent::Bool, cleanup::Bool, on_write::Franklin.var"#236#239", log::Bool, host::String, show_warnings::Bool, fail_on_warning::Bool, launch::Bool, no_set_paths::Bool, join_to_prepath::String)
    @ Franklin ~/.julia/packages/Franklin/2KNQE/src/manager/franklin.jl:138
 [14] serve()
    @ Franklin ~/.julia/packages/Franklin/2KNQE/src/manager/franklin.jl:70
 [15] top-level scope
    @ none:1

It would be nice to have support for Markdown, CommonMark, Html, and HypertextLiteral.

@tlienart
Copy link
Owner

tlienart commented Oct 18, 2021

The contract for lx* functions is that they return a String that can be consumed by Franklin, nothing else. If you have a workflow which requires some intermediate representation such as md"..." then you would still have to extract the "string" value at the return level. So in the specific case you mention:

...
  md_str = md"foo bar **baz**"
  return string(md_str)
end

Edit you can protect a string to guarantee that Franklin doesn't touch it by putting it in ~~~...~~~. So for instance you could imagine using a CommonMark workflow which takes some markdown and generates some HTML and have your return be ~~~$(the_result_from_the_CM_conversion)~~~ and Franklin will leave it as is.

@schlichtanders
Copy link
Author

thank you, good to know that this is the only intended use.

Then my confusion actually arose from hfun_... being more forgiving on the return value - here you can use an md"..." string.
From a user perspective it is confusing, why the one interface is forgiving and the other not - they are all "franklin interfaces" .

@tlienart
Copy link
Owner

tlienart commented Oct 18, 2021

For clarification (I think this is somewhere in the docs but might not be prominently so). There are basically two phases for a Franklin page:

  1. the markdown pass, which converts a document into html possibly with {{...}} still to be resolved
  2. the html pass, which converts a html and resolves any {{...}}

the order is important because some of these {{...}} are appended to head/foot of the page.

In that sense, the lx_* get resolved at phase (1) and therefore are expected to produce a string similar to the rest of the document around it (i.e. markdown). The hfun_* however get resolved at phase (2) and so HTML is expected.

Of course this can be tweaked by making the lx* output a protected string (as per my previous comment) or using a markdown->html conversion step within a hfun* which is also allowed.

Edit: the interface should be unforgiving for hfun as well so I agree that it should constraint to AbstractString.

@schlichtanders
Copy link
Author

Thanks for the general design summary. It helps quite a lot having understood this distinction

Edit: the interface should be unforgiving for hfun as well so I agree that it should constraint to AbstractString.

Perfect, that would resolve my concerns

@schlichtanders
Copy link
Author

I created a new issue for that. Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants