In this post only the original code is kept. For most recent versions visit GH.
In order to install:
ResourceFunction["GitHubInstall"]["kubapod", "m2md"]
Or visit GH readme.
Here are related solutions in case this does not fit your needs:
Original post
Features
Markdown capabilities differ from environment to environment so I expect this will be only a base that one can modify so it fits his/her needs best.
StackExchange MD supports only H1-H3 headers and Sub/sub/Titles are cell styles which I've associated with them. Sub/sub/Sections are associated with H4-H6 so you work more with those you may change it since the latter group will look here as ordinary text.
An Output cells generated by whatever // TraditionalForm
are automatically $\LaTeX$ blocks. An Inline TraditionalForm
is inline $\LaTeX$.
At the moment only this one type of Output cell is parsed.
Unknown cell styles leave MD comment: [//]: # (No rules defined for *CellStyleName*)
, which is not displayed ofc.
I tried to convert Hyperlinks
and it seems to work.
Sub and Subsub ItemsNumbered
only get prefix in form: 1., 2.
etc. I could put there what we see in MMA, like 1.2.1.
but it doesn't seem to be supported in MD. Or rather, it is sometimes but up to SubitemNumbered
and no deeper.
Tests
I've put it as a procedure in palette which can convert things quite nicely.
This is a test notebook I'm using and the result of tests pasted here:
CreateDocument@ Uncompress@ "1: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"
(^ double click to select. Don't evaluate this if the last edit was made by someone else than me)
Result
Title bold
Subtitle italic
Subsubtitle
Enter text here. Enter TraditionalForm input for evaluation in a separate cell below:
Integrate[x, x] + Sqrt[x] // TraditionalForm
$$\frac{x^2}{2}+\sqrt{x}$$
Item
asdasd
ItemParagraph
Text cell
a TraditionalForm expression: $\frac{x^2}{2}+\sqrt{x}$
(both are in InlineCells)
Text with inline formula: $4$.
ItemNumbered
ItemParagraph
SubitemNumbered
SubitemParagraph
SubsubitemNumbered
SubsubitemParagraph
fun[x_] := 1
/Result
Code for palette
CreatePalette[#, CellContext -> Notebook] &@DynamicModule[{},
Button["Export to Markdown",
CreateDocument@exportMD@InputNotebook[]],
Initialization :> (
itemIndent = " ";
codeIndent = " ";
itemMark = "+ ";
itemPrefix = Function[{cellObj, style}, Module[{
ind, depth, numberedQ, paragraphQ},
ind = ToString@CurrentValue[cellObj, {"CounterValue", style}];
depth = StringCount[style, "sub", IgnoreCase -> True];
numberedQ =
StringCount[style, "numbered", IgnoreCase -> True] > 0;
paragraphQ =
StringCount[style, "paragraph", IgnoreCase -> True] > 0;
StringJoin@Flatten@{
ConstantArray[itemIndent, depth + If[paragraphQ, 2, 1]],
Which[
numberedQ, {ind, ". "},
paragraphQ, "",
True, itemMark]
}
]];
prefix[styleName_] := Switch[styleName,
"Title", "# ",
"Subtitle", "## ",
"Subsubtitle", "### ",
"Section", "#### ",
"Subsection", "##### ",
"Subsubsection", "###### ",
"Text", "",
"items", itemPrefix,
"code", codeIndent
];
styleWrapper[opts___] := Module[{italic, bold, wrapper
},
italic = MemberQ[{opts}, Verbatim[Rule][FontSlant, "Italic"]];
bold = MemberQ[{opts}, Verbatim[Rule][FontWeight, "Bold"]];
wrapper = Which[
bold, "**",
italic, "*",
True, ""
];
wrapper <> # <> wrapper &
];
parseCodeData[data_] := StringReplace[
First[FrontEndExecute[FrontEnd`ExportPacket[data, "InputText"]]],
"\n" -> "\n" <> codeIndent
];
textStyleQ = (StringCount[#, "title" | "section" | "text",
IgnoreCase -> True] > 0) &;
itemStyleQ = (StringCount[#, "item", IgnoreCase -> True] >
0) &;
codeStyleQ = MemberQ[{"Code", "Input"}, #] &;
exportMD[nb_NotebookObject] :=
StringJoin@Flatten[exportMD /@ Cells[nb]];
exportMD[cellObj_CellObject] :=
exportMD[NotebookRead[cellObj], cellObj];
exportMD[cell_Cell, cellObj_CellObject] :=
exportMD[#2, #, cellObj] & @@ cell;
exportMD[style_?textStyleQ, data_, cellObj_CellObject] := {
prefix[style], addPrefix[style] /@ Flatten@{parseData[data]},
"\n\n"
};
addPrefix[style_][expr : Except[_String]] := expr;
addPrefix[style_][s_String] :=
StringReplace[s, "\n" -> "\n" <> prefix[style]];
exportMD[style_?itemStyleQ, data_, cellObj_CellObject] := {
prefix["items"][cellObj, style], parseData@data, "\n\n"};
exportMD[style_?codeStyleQ, data_, cellObj_CellObject] := {
"\n\n----------\n\n",
codeIndent, parseCodeData@data,
"\n\n"};
exportMD["Output", BoxData[FormBox[boxes_, TraditionalForm]],
cellObj_CellObject] := TemplateApply[
"$$``$$\n\n", {boxesToTeX@boxes}
];
parseData[list_List] := parseData /@ list;
parseData[string_String] := string;
parseData[data_ (BoxData | TextData)] :=
List @@ (parseData /@ data);
parseData[cell_Cell] :=
parseData@First@cell; (*inlince cells style skipped*)
parseData[StyleBox[expr_, opts___]] :=
styleWrapper[opts]@parseData[expr];
parseData[
FormBox[boxes : Except[_TagBox], TraditionalForm, ___]] :=
Module[{teXForm},
teXForm = boxesToTeX@boxes;
"$" <> teXForm <> "$"
];
parseData[
box : ButtonBox[_, ___, BaseStyle -> "Hyperlink", ___]] :=
Module[{label, url},
{label, url} = {#, #2} & @@ ToExpression[box];
TemplateApply[
"[``](``)", {StringJoin@Flatten@{parseData@label}, url}]
];
(*default behaviour for boxes*)
parseData[boxes_] := parseData@First@boxes;
(*default behaviour for cell styles*)
exportMD[s_, ___] :=
TemplateApply["[//]: # (No rules defined for ``)\n\n", {s}];
boxesToTeX = ToString[ToExpression@#, TeXForm] &;
)
]