gpoore / codebraid-preview-vscode

Preview Pandoc Markdown in VS Code, and execute code blocks and inline code with Codebraid
Other
29 stars 4 forks source link

Codebraid Preview

Codebraid Preview provides a Pandoc-based document preview within VS Code. All of Pandoc's extensions to Markdown syntax are fully supported—because the preview is generated by Pandoc itself! The preview also includes built-in support for LaTeX, Org, reStructuredText, and Textile. Codebraid Preview is compatible with any text-based document format supported by Pandoc. Additional formats can typically be enabled by defining a few settings.

There is scroll sync between the document source and the preview for Markdown, LaTeX, Org, reStructuredText, and Textile. Scroll sync support can be extended for additional formats. Documents can be exported via Pandoc. Several export formats are predefined, including HTML, LaTeX, PDF, PowerPoint, and Word. Additional formats can be defined in settings. There is optional support for executing code blocks and inline code to embed their output in the preview and in exported documents. This is performed by Codebraid and is currently limited to Markdown documents.

VS Code editor with Codebraid Preview

Features

Setup and requirements

Pandoc

Install Pandoc. The latest version is recommended. Version 3.1.1+ is required for scroll sync for formats besides commonmark_x, commonmark, and gfm. Versions before 2.17.1.1 may work but will have reduced functionality, including scroll sync issues with YAML metadata.

Default Markdown reader

By default, Markdown documents are treated as Pandoc's commonmark_x format, since this provides the best scroll sync experience while still supporting most Pandoc extensions to Markdown syntax. If you need features that are only available in Pandoc's Markdown (markdown), modify the extension setting codebraid.preview.pandoc.build, under *.md, to change reader from commonmark_x to markdown. This will cause scroll sync to be less accurate in some circumstances, since scroll sync data must be reconstructed by Codebraid Preview instead of being generated by Pandoc itself.

Codebraid

For code execution, install the latest version of Codebraid. Codebraid currently only supports code execution in Markdown documents.

Security

You may want to review the default security settings under codebraid.preview.security. For example, if you are using remote images, you will need to enable codebraid.preview.security.allowRemoteImages. If you are using Codebraid with Jupyter output that involves scripts, then you will need to enable inline scripts or local scripts.

Adding support for additional input formats

To add basic support for an additional document format, simply create a defaults file in the document directory that specifies from or reader. See setting codebraid.preview.pandoc.defaultsFile. Or define an additional file extension under codebraid.preview.pandoc.build.

For formats with built-in Pandoc support, please open an issue on GitHub to request scroll sync. For custom formats, look in the Git repo under pandoc/lib/readerlib.lua and pandoc/readers for details about adding scroll sync using a short Lua wrapper script.

Jupyter notebooks

The preview is compatible with Jupyter notebooks (ipynb). Simply add the following to settings.json, under codebraid.preview.pandoc.build:

"*.ipynb": {
    "reader": "ipynb",
    "preview": {
        "html": {
            "defaults": {},
            "options": []
        }
    },
    "export": {}
},

Jupyter notebooks have some limitations compared to other formats. Scroll sync is not currently supported. The preview currently only updates when the notebook is saved; the preview does not update live as you type.

VS Code already provides a built-in notebook editor. A Pandoc-based preview for Jupyter notebooks will primarily be useful when Pandoc filters or similar features are used to customize a notebook during export.

A note on input formats and commonmark_x

By default, Markdown documents are treated as Pandoc's commonmark_x format, which is different from Pandoc's default markdown format. Scroll sync data is only generated by Pandoc for CommonMark-based formats, and commonmark_x is the most powerful of these. For other formats, Codebraid Preview must reconstruct scroll sync data, and this can be less accurate in some circumstances.

The Pandoc Roadmap provides details about commonmark_x features. commonmark_x currently lacks some markdown features that are summarized below. If you need these features, you can switch the input format to markdown by modifying the extension setting codebraid.preview.pandoc.build, under *.md, to change reader from commonmark_x to markdown. Or you can create a defaults file _codebraid_preview.yaml in the document directory and set from: markdown in it. Keep in mind that switching to markdown will make scroll sync less accurate in some circumstances.

Summary of some key features not present in commonmark_x compared to markdown:

A note on filters

Scroll sync is provided for CommonMark-based formats using Pandoc's sourcepos extension. For other formats with scroll sync, Codebraid Preview provides an emulation of sourcepos. In either case, this inserts Div and Span nodes into the Pandoc AST that contain information about source file origin location in a data-pos attribute. If you use filters with your documents and want to make sure that the preview is accurate while retaining scroll sync capabilities, make sure that your filters skip these nodes and only remove them if empty. For example, in a Lua filter these nodes can be detected by checking node.attributes['data-pos'] ~= nil.

Block-level filters typically must be modified to be compatible with Pandoc's sourcepos because it inserts many Div nodes with a data-pos attribute into the AST. Block-level filters typically do not require modification for Codebraid Preview's sourcepos because it only inserts Div nodes into the AST to wrap CodeBlock and RawBlock nodes. Pandoc's sourcepos is used by default when available (CommonMark-based formats commonmark, commonmark_x, and gfm). To use Codebraid Preview's sourcepos instead, change the setting codebraid.preview.pandoc.preferPandocSourcepos to false.

Custom Pandoc HTML templates

The preview is compatible with custom Pandoc HTML templates. Custom templates should typically be based on the default Pandoc template. The default Pandoc template can be viewed by running pandoc --print-default-template=html.

Custom templates must have this general format (case insensitive):

<!-- ... -->       {optional comment(s)}
<!doctype html>    {required}
<!-- ... -->       {optional comment(s)}
<html {attrs}>     {required; optional attributes}
<!-- ... -->       {optional comment(s)}
<head>             {required}
...

Currently, any optional attributes in the html tag must have names matching the regex [a-zA-Z][a-zA-Z0-9]*(?:[:-][a-zA-Z0-9]+)* with quoted values.

Custom templates must also include CSS for the preview to display properly. This can be done following the default Pandoc template:

$for(css)$
  <link rel="stylesheet" href="https://github.com/gpoore/codebraid-preview-vscode/blob/master/$css$" />
$endfor$

The preview sets the Pandoc template variable codebraid_preview to true. When necessary, custom templates can use this to adapt to Codebraid Preview. For example:

$if(codebraid_preview)$
...
$else$
...
$endif$

Known limitations

Some Pandoc options have limited preview support or require special settings.

Extension settings

Document build and display

Pandoc

Security

The HTML preview is displayed using a webview. These settings determine which local and remote resources, such as images and scripts, can be loaded by the webview. These settings only determine the resources that the webview can load. They do not affect the resources that Pandoc can access or determine which resources Pandoc can embed in the HTML preview document (see note below).

By default, all remote resources are disabled. By default, local resources can only be loaded from the current workspace folders, the document directory, and the default Pandoc user data directory (see output of pandoc --version for location). Additional local locations can be added via security.extraLocalResourceRoots. All types of local resources are permitted by default except for scripts. Inline scripts are also not permitted by default, except for those bundled as part of the extension.

Scripting capabilities should only be enabled when using documents that you trust. Styles (CSS), particularly when combined with images/media or fonts, can also have security implications, especially when remote resources are involved.

Note on limitations of security settings: Many security settings determine which resources the webview can load. However, the Pandoc option --embed-resources uses data: URIs to incorporate the contents of linked scripts, stylesheets, images, and videos directly into the HTML. If you choose to use --embed-resources, be aware that this makes these security settings irrelevant, since content is embedded in the HTML rather than being loaded from a local or remote source. Similarly, --extract-media makes most image and media security settings irrelevant, because it copies or downloads all images and media to a local temp directory that is accessible by default. --extract-media is required to preview Jupyter notebooks and is automatically enabled only for that case.

Inline

Embedded

Local

Remote

Resource roots

Codebraid configuration

When Codebraid is used to run code, the codebraid executable is found by searching the following locations.

  1. If a Python interpreter is set in VS Code, the interpreter installation is checked for a codebraid executable.

    Notice that a Python interpreter can be set at the file level or workspace level (Ctrl+Shift+P, then Python: Select Interpreter, or configure python.defaultInterpreterPath in a workspace settings.json). A Python interpreter can also be configured in global User Settings (File, Preferences, Settings, Python: Default Interpreter Path). Only the first Python interpreter that is set in the file/workspace/global sequence is checked for a codebraid executable.

    For more details about configuring Python in VS Code, see https://code.visualstudio.com/docs/python/environments.

  2. If a Python interpreter is not set, or its installation does not include a codebraid executable, then the first codebraid executable on PATH is used. There will be a warning message if a Python interpreter is set but does not include codebraid, so that codebraid on PATH is used as a fallback.

If the codebraid executable is part of an Anaconda installation, it is launched via conda run so that the relevant conda environment is activated. For other environments and installations, the codebraid executable is run directly.

Security

The HTML preview is displayed using a webview. A content security policy is used to restrict what is possible in the webview. Inline styles are permitted. Local resources associated with a document, except for scripts, are enabled by default. All remote resources are disabled by default. To customize webview capabilities, see settings under codebraid.preview.security. All resources bundled with the extension (styles, fonts, and scripts) are always allowed, to support features like KaTeX math and scroll sync.

Code is never automatically executed with Codebraid. Code is only ever executed when a Codebraid class is added to a code block or inline code, and then the "Codebraid" button is clicked (or the "Run code with Codebraid" command is invoked).

Supporting this project

Codebraid Preview is open-source software released under the BSD 3-Clause License. If you use it regularly, please consider supporting further development through GitHub Sponsors.