WolframResearch / WolframLanguageForJupyter

Wolfram Language kernel for Jupyter notebooks
MIT License
1.05k stars 126 forks source link

Render output expression between $$ $$ as TeX in VS Code #127

Open pammacdotnet opened 2 years ago

pammacdotnet commented 2 years ago

Dear developers,

The output delivered by the standard Wolfram Jupyter interface and VS code is different when the output expression is between $$ $$. Please see image attached. I think the behaviour should be the same (left is ordinary Jupyter and right is VS Code notebook support): I also attach a veeeeery minimal notebook example renamed as .txt (to skip upload restrictions) wolfram kernel minimal example.ipynb.txt. It just should render "1/2" as \frac{1}{2}. Again, the rendering works fine in the default Jupyter notebook web environment, but not in VS Code (v1.66.0-insider + Jupyter extension v2022.3.1000652335).

After exploring my minimal example, people in the VS Code side have pointed out that it looks like every character is encoded as its html number, and Jupyter knows to treat that differently: <div>&#36;&#36;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#50;&#125;&#36;&#36;</div> which plain html renders as: $$\frac{1}{2}$$"

They recommend the following:

Could you please fix the Wolfram Jupyter Kernel so that // TeXForm output is correctly rendered in VS Code?? VS Code is now a wonderful environment for Notebook editing and Wolfram development.

rstanuwijaya commented 2 years ago

+1 this feature is much needed

HellOwhatAs commented 2 years ago

Hi,

It seems that those html elements are generated from line 297 of RequestHandlers.wl. (marked as "text/html")

And to display latex, I suggest "text/latex". Below gets the latex string of output.

"text/latex" -> "$"<>ToString[First[totalResult["EvaluationResult"]],TeXForm]<>"$"

However, display all outputs in "text/latex" mode will cause a problem that pictures will be displayed in tex form wrongly

微信截图_20220716204655

.

Thus use If[condition,t,f,u] to decide to choose "text/latex" mode or "text/html" mode.

My solution is to change the first element of the list ruled by "data" in line 294 from

"text/html" ->
    If[
        loopState["isCompleteRequestSent"],
        (* if an is_complete_request has been sent, assume jupyter-console is running the kernel,
            and do not generate HTML *)
        "",
        (* otherwise, output the results in a grid *)
        If[
            Length[totalResult["EvaluationResult"]] > 1,
            StringJoin[
                (* add grid style *)
                "<style>
                    .grid-container {
                        display: inline-grid;
                        grid-template-columns: auto;
                    }
                </style>
                <div>",
                (* display error message *)
                errorMessage,
                (* start the grid *)
                "<div class=\"grid-container\">",
                (* display the output lines *)
                Table[
                    {
                        (* start the grid item *)
                        "<div class=\"grid-item\">",
                        (* show the output line *)
                        toOut[totalResult["EvaluationResult"][[outIndex]]],
                        (* end the grid item *)
                        "</div>"
                    },
                    {outIndex, 1, Length[totalResult["EvaluationResult"]]}
                ],
                (* end the element *)
                "</div></div>"
            ],
            StringJoin[
                (* start the element *)
                "<div>",
                (* display error message *)
                errorMessage,
                (* if there are messages, but no results, do not display a result *)
                If[
                    Length[totalResult["EvaluationResult"]] == 0,
                    "",
                    (* otherwise, display a result *)
                    toOut[First[totalResult["EvaluationResult"]]]
                ],
                (* end the element *)
                "</div>"
            ]
        ]
    ]

to

If[Equal[Head[First[totalResult["EvaluationResult"]]],TraditionalForm],
    "text/latex" -> "$"<>ToString[First[totalResult["EvaluationResult"]],TeXForm]<>"$",
    "text/html" ->
        If[
            loopState["isCompleteRequestSent"],
            (* if an is_complete_request has been sent, assume jupyter-console is running the kernel,
                and do not generate HTML *)
            "",
            (* otherwise, output the results in a grid *)
            If[
                Length[totalResult["EvaluationResult"]] > 1,
                StringJoin[
                    (* add grid style *)
                    "<style>
                        .grid-container {
                            display: inline-grid;
                            grid-template-columns: auto;
                        }
                    </style>    
                    <div>",
                    (* display error message *)
                    errorMessage,
                    (* start the grid *)
                    "<div class=\"grid-container\">",
                    (* display the output lines *)
                    Table[
                        {
                            (* start the grid item *)
                            "<div class=\"grid-item\">",
                            (* show the output line *)
                            toOut[totalResult["EvaluationResult"][[outIndex]]],
                            (* end the grid item *)
                            "</div>"
                        },
                        {outIndex, 1, Length[totalResult["EvaluationResult"]]}
                    ],
                    (* end the element *)
                    "</div></div>"
                ],
                StringJoin[
                    (* start the element *)
                    "<div>",
                    (* display error message *)
                    errorMessage,
                    (* if there are messages, but no results, do not display a result *)
                    If[
                        Length[totalResult["EvaluationResult"]] == 0,
                        "",
                        (* otherwise, display a result *)
                        toOut[First[totalResult["EvaluationResult"]]]
                    ],
                    (* end the element *)
                    "</div>"
                ]
            ]
        ],
    "text/html" ->
    If[
        loopState["isCompleteRequestSent"],
        (* if an is_complete_request has been sent, assume jupyter-console is running the kernel,
            and do not generate HTML *)
        "",
        (* otherwise, output the results in a grid *)
        If[
            Length[totalResult["EvaluationResult"]] > 1,
            StringJoin[
                (* add grid style *)
                "<style>
                    .grid-container {
                        display: inline-grid;
                        grid-template-columns: auto;
                    }
                </style>    
                <div>",
                (* display error message *)
                errorMessage,
                (* start the grid *)
                "<div class=\"grid-container\">",
                (* display the output lines *)
                Table[
                    {
                        (* start the grid item *)
                        "<div class=\"grid-item\">",
                        (* show the output line *)
                        toOut[totalResult["EvaluationResult"][[outIndex]]],
                        (* end the grid item *)
                        "</div>"
                    },
                    {outIndex, 1, Length[totalResult["EvaluationResult"]]}
                ],
                (* end the element *)
                "</div></div>"
            ],
            StringJoin[
                (* start the element *)
                "<div>",
                (* display error message *)
                errorMessage,
                (* if there are messages, but no results, do not display a result *)
                If[
                    Length[totalResult["EvaluationResult"]] == 0,
                    "",
                    (* otherwise, display a result *)
                    toOut[First[totalResult["EvaluationResult"]]]
                ],
                (* end the element *)
                "</div>"
            ]
        ]
    ]
]

( The modified RequestHandlers.wl file RequestHandlers.wl.txt (also renamed) )

After modifying (or replacing) RequestHandlers.wl, all elements in TraditionalForm (elements whose Head is TraditionalForm) will be displayed in "text/latex" mode.

微信截图_20220716205108
pammacdotnet commented 2 years ago

Great solution! Can this be added to WL4J?