Giter Site home page Giter Site logo

micromark / micromark-extension-math Goto Github PK

View Code? Open in Web Editor NEW
11.0 7.0 3.0 158 KB

micromark extension to support math (`$C_L$`)

Home Page: https://unifiedjs.com

License: MIT License

JavaScript 100.00%
micromark micromark-extension math latex katex tex

micromark-extension-math's Introduction

micromark-extension-math

Build Coverage Downloads Size Sponsors Backers Chat

micromark extensions to support math ($C_L$).

Contents

What is this?

This package contains two extensions that add support for math syntax in markdown to micromark.

As there is no spec for math in markdown, this extension follows how code (fenced and text) works in Commonmark, but uses dollars.

When to use this

This project is useful when you want to support math in markdown. Extending markdown with a syntax extension makes the markdown less portable. LaTeX equations are also quite hard. But this mechanism works well when you want authors, that have some LaTeX experience, to be able to embed rich diagrams of math in scientific text.

You can use these extensions when you are working with micromark already.

When you need a syntax tree, you can combine this package with mdast-util-math.

All these packages are used remark-math, which focusses on making it easier to transform content by abstracting these internals away.

Install

This package is ESM only. In Node.js (version 16+), install with npm:

npm:

npm install micromark-extension-math

In Deno with esm.sh:

import {math, mathHtml} from 'https://esm.sh/micromark-extension-math@3'

In browsers with esm.sh:

<script type="module">
  import {math, mathHtml} from 'https://esm.sh/micromark-extension-math@3?bundle'
</script>

Use

Say our document example.md contains:

Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following equation.

$$
L = \frac{1}{2} \rho v^2 S C_L
$$

…and our module example.js looks as follows:

import fs from 'node:fs/promises'
import {micromark} from 'micromark'
import {math, mathHtml} from 'micromark-extension-math'

const output = micromark(await fs.readFile('example.md'), {
  extensions: [math()],
  htmlExtensions: [mathHtml()]
})

console.log(output)

…now running node example.js yields (abbreviated):

<p>Lift(<span class="math math-inline"><span class="katex"></span></span>) can be determined by Lift Coefficient (<span class="math math-inline"><span class="katex"></span></span>) like the following equation.</p>
<div class="math math-display"><span class="katex-display"><span class="katex"></span></span></div>

API

This package exports the identifiers math and mathHtml. There is no default export.

The export map supports the development condition. Run node --conditions development module.js to get instrumented dev code. Without this condition, production code is loaded.

math(options?)

Create an extension for micromark to enable math syntax.

Parameters
  • options (Options, default: {}) — configuration
Returns

Extension for micromark that can be passed in extensions, to enable math syntax (Extension).

mathHtml(options?)

Create an extension for micromark to support math when serializing to HTML.

👉 Note: this uses KaTeX to render math.

Parameters
Returns

Extension for micromark that can be passed in htmlExtensions, to support math when serializing to HTML (HtmlExtension).

HtmlOptions

Configuration for HTML output (optional).

👉 Note: passed to katex.renderToString. displayMode is overwritten by this plugin, to false for math in text (inline), and true for math in flow (block).

Type
type Options = Omit<import('katex').KatexOptions, 'displayMode'>

Options

Configuration (TypeScript type).

Fields
  • singleDollarTextMath (boolean, default: true) — whether to support math (text, inline) with a single dollar. Single dollars work in Pandoc and many other places, but often interfere with “normal” dollars in text. If you turn this off, you use two or more dollars for text math.

Authoring

When authoring markdown with math, keep in mind that math doesn’t work in most places. Notably, GitHub currently has a really weird crappy client-side regex-based thing. But on your own (math-heavy?) site it can be great! You can use code (fenced) with an info string of math to improve this, as that works in many places.

HTML

Math (flow) does not relate to HTML elements. MathML, which is sort of like SVG but for math, exists but it doesn’t work well and isn’t widely supported. Instead, this uses KaTeX, which generates MathML as a fallback but also generates a bunch of divs and spans so math look pretty. The KaTeX result is wrapped in <div> (for flow, block) and <span> (for text, inline) elements, with two classes: math and either math-display or math-inline.

When turning markdown into HTML, each line ending in math (text) is turned into a space.

CSS

The HTML produced by KaTeX requires CSS to render correctly. You should use katex.css somewhere on the page where the math is shown to style it properly. At the time of writing, the last version is:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css">

Syntax

Math forms with the following BNF:

; Restriction: the number of markers in the closing sequence must be equal
; to the number of markers in the opening sequence.
math_text ::= sequence_text 1*byte sequence_text
math_flow ::= fence_open *( eol *line ) [ eol fence_close ]

; Restriction: not preceded or followed by the marker.
sequence_text ::= 1*'$'

fence_open ::= sequence_flow meta
; Restriction: the number of markers in the closing fence sequence must be
; equal to or greater than the number of markers in the opening fence
; sequence.
fence_close ::= sequence_flow *space_or_tab
sequence_flow ::= 2*'$'
; Restriction: the marker cannot occur in `meta`
meta ::= 1*line

; Character groups for informational purposes.
byte ::= 0x00..=0xFFFF
eol ::= '\n' | '\r' | '\r\n'
line ::= byte - eol

The above grammar shows that it is not possible to create empty math (text). It is possible to include the sequence marker (dollar) in math (text), by wrapping it in bigger or smaller sequences:

Include more: $a$$b$ or include less: $$a$b$$.

It is also possible to include just one marker:

Include just one: $$ $ $$.

Sequences are “gready”, in that they cannot be preceded or followed by more markers. To illustrate:

Not math: $$x$.

Not math: $x$$.

Escapes work, this is math: \$$x$.

Escapes work, this is math: $x$\$.

Yields:

<p>Not math: $$x$.</p>
<p>Not math: $x$$.</p>
<p>Escapes work, this is math: $<span></span>.</p>
<p>Escapes work, this is math: <span></span>$.</p>

That is because, when turning markdown into HTML, the first and last space, if both exist and there is also a non-space in the math, are removed. Line endings, at that stage, are considered as spaces.

As the math (flow) construct occurs in flow, like all flow constructs, it must be followed by an eol (line ending) or eof (end of file).

The above grammar does not show how indentation of each line is handled. To parse math (flow), let x be the number of space_or_tab characters before the opening fence sequence, after interpreting tabs based on how many virtual spaces they represent. Each line of text is then allowed (not required) to be indented with up to x spaces or tabs, which are then ignored as an indent instead of being considered as part of the content. This indent does not affect the closing fence. It can be indented up to a separate 3 real or virtual spaces. A bigger indent makes it part of the content instead of a fence.

The meta part is interpreted as the string content type. That means that character escapes and character references are allowed.

The optional meta part is ignored: it is not used when parsing or rendering.

Types

This package is fully typed with TypeScript. It exports the additional types HtmlOptions and Options.

Compatibility

Projects maintained by the unified collective are compatible with maintained versions of Node.js.

When we cut a new major release, we drop support for unmaintained versions of Node. This means we try to keep the current release line, micromark-extension-math@^3, compatible with Node.js 16.

This package works with micromark version 3 and later.

Security

This package is safe assuming that you trust KaTeX. Any vulnerability in it could open you to a cross-site scripting (XSS) attack.

Related

Contribute

See contributing.md in micromark/.github for ways to get started. See support.md for ways to get help.

This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.

License

MIT © Titus Wormer

micromark-extension-math's People

Contributors

tumidi avatar wooorm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

micromark-extension-math's Issues

Parsing fails when disabling construct `codeIndented` (using `micromark-extension-mdx-md`)

Initial checklist

Affected packages and versions

[email protected]

Link to runnable example

https://codepen.io/tumidi/pen/rNqxMjm

Steps to reproduce

The CodePen shows that parsing display math fails when nested in two MDX elements and using indent of four spaces.

Might be related or similar to micromark/micromark-extension-gfm-table#10.

Expected behavior

Display math should be parsed correctly.

Actual behavior

Parsing fails with Expected a closing tag for <div>.

Runtime

Other (please specify in steps to reproduce)

Package manager

Other (please specify in steps to reproduce)

OS

Linux

Build and bundle tools

Other (please specify in steps to reproduce)

Produces wrong output compared to github math

Initial checklist

Affected packages and versions

"micromark-extension-math": "^2.1.2",

Link to runnable example

No response

Steps to reproduce

This is what I have

const mdToHtml = (md) => {
   const result = micromark(md, {
      extensions: [gfm(), math()],
      htmlExtensions: [gfmHtml(), mathHtml()]
   })
   return result
}

For the input

$\left[\mathrm{ML}^2 \mathrm{~T}^{-2} \mathrm{~K}\right]$

It generates out put which contains extra [ML2 T−2 K−1] right after the equation

See screenshot for generated output
Screenshot 2023-06-07 at 10 46 57 PM

Expected behavior

Expect it to generate only math formula without extra output

Actual behavior

Generates exra output

Runtime

No response

Package manager

No response

OS

No response

Build and bundle tools

No response

"$20,000 and $30,000" should’t parse as math (if remark-math and micromark-extension-math follows Pandoc as remark-math 3.0 did)

Older remark-math handled it same as pandoc: remarkjs/remark-math#35. I consider this a regression.

Initial checklist

Affected packages and versions

remark-math 6.0.0

Link to runnable example

Codesandbox

Steps to reproduce

Codesandbox

import remarkParse from "remark-parse";
import { unified } from "unified";
import remarkMath from "remark-math";

const sourceMarkdown = `$20,000 and $30,000`;

document.getElementById("source").textContent = sourceMarkdown;

const processor = unified().use(remarkParse).use(remarkMath);

processor
  .run(processor.parse(sourceMarkdown))
  .then((file) => {
    document.getElementById("result").textContent = JSON.stringify(
      file,
      null,
      2
    );
  })
  .catch((err) => (document.getElementById("error").textContent = err));

Expected behavior

It shouldn't parse as math.

Actual behavior

parses as inline math.

{
  "type": "root",
  "children": [
    {
      "type": "paragraph",
      "children": [
        {
          "type": "inlineMath",
          "value": "20,000 and ",
          "data": {
            "hName": "code",
            "hProperties": {
              "className": [
                "language-math",
                "math-inline"
              ]
            },
            "hChildren": [
              {
                "type": "text",
                "value": "20,000 and "
              }
            ]
          },
          "position": {
            "start": {
              "line": 1,
              "column": 1,
              "offset": 0
            },
            "end": {
              "line": 1,
              "column": 14,
              "offset": 13
            }
          }
        },
        {
          "type": "text",
          "value": "30,000",
          "position": {
            "start": {
              "line": 1,
              "column": 14,
              "offset": 13
            },
            "end": {
              "line": 1,
              "column": 20,
              "offset": 19
            }
          }
        }
      ],
      "position": {
        "start": {
          "line": 1,
          "column": 1,
          "offset": 0
        },
        "end": {
          "line": 1,
          "column": 20,
          "offset": 19
        }
      }
    }
  ],
  "position": {
    "start": {
      "line": 1,
      "column": 1,
      "offset": 0
    },
    "end": {
      "line": 1,
      "column": 20,
      "offset": 19
    }
  }
}

Runtime

No response

Package manager

No response

OS

No response

Build and bundle tools

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.