Compare commits
10 Commits
f9aed50712
...
9b3ec3d024
Author | SHA1 | Date | |
---|---|---|---|
|
9b3ec3d024 | ||
|
63f216c575 | ||
|
2671ef78fb | ||
|
dbdf78b5fe | ||
|
232e443aeb | ||
|
5a671c036a | ||
|
2ca3afba36 | ||
|
c4e97028fb | ||
|
d7abc3b8c5 | ||
|
c9db67f2a0 |
25
README.md
25
README.md
@ -7,18 +7,37 @@ To install Contrast as your default theme, first install this repository in the
|
||||
$ cd themes/
|
||||
$ git clone https://github.com/niklasbuschmann/contrast-hugo.git
|
||||
|
||||
Second, specify `contrast-hugo` as your default theme in the `config.yaml` file. Just add the line
|
||||
Second, specify `contrast-hugo` as your default theme in the `config.toml` file. Just add the line
|
||||
|
||||
theme: "contrast-hugo"
|
||||
theme = "contrast-hugo"
|
||||
|
||||
at the top of the file.
|
||||
|
||||
### Example config
|
||||
|
||||
```
|
||||
title = "Davids Blog"
|
||||
author = "David Wallace"
|
||||
theme = "contrast-hugo"
|
||||
|
||||
[params]
|
||||
minimal = false
|
||||
excerpts = false
|
||||
description = "my blog"
|
||||
|
||||
[menu]
|
||||
[[menu.main]]
|
||||
identifier = "about"
|
||||
name = "About"
|
||||
url = "/about/"
|
||||
weight = 10
|
||||
```
|
||||
|
||||
## Based on
|
||||
|
||||
- [Hyde](https://github.com/poole/hyde)
|
||||
- [Minima](https://github.com/jekyll/minima)
|
||||
- [KaTeX](https://katex.org/)
|
||||
- [Font-Awesome](https://fontawesome.com/)
|
||||
|
||||
## License
|
||||
|
||||
|
@ -7,16 +7,18 @@
|
||||
<meta name="description" content="{{ .Description | default .Site.Params.description }}">
|
||||
{{- end }}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{{ .Site.BaseURL }}css/index.css">
|
||||
<link rel="stylesheet" href="{{ .Site.BaseURL }}css/{{ if .Site.Params.minimal }}minimal.css{{ else }}index.css{{ end }}">
|
||||
<link rel="canonical" href="{{ .Permalink }}">
|
||||
<link rel="alternate" type="application/rss+xml" href="{{ with .OutputFormats.Get "RSS" }}{{ .RelPermalink }}{{ end }}" title="{{ .Site.Title }}">
|
||||
{{- if or .Params.math .Site.Params.math }}
|
||||
{{ partial "math.html" . }}
|
||||
<link rel="stylesheet" href="{{ .Site.BaseURL }}katex/katex.min.css">
|
||||
<script defer src="{{ .Site.BaseURL }}katex/katex.min.js"></script>
|
||||
<script defer src="{{ .Site.BaseURL }}katex/contrib/auto-render.min.js" onload="renderMathInElement(document.body)"></script>
|
||||
{{- end }}
|
||||
|
||||
<header>
|
||||
{{ if not (gt (len .Site.Menus) 1) }}
|
||||
<a href="{{ .Site.BaseURL }}">{{ .Site.Title }}</a>
|
||||
<a href="{{ .Site.BaseURL }}" class="title">{{ .Site.Title }}</a>
|
||||
{{ end }}
|
||||
{{ range $menu, $items := .Site.Menus }}
|
||||
<nav>
|
||||
|
@ -6,12 +6,29 @@
|
||||
{{ $Pages = where site.RegularPages "Type" "in" .Site.Params.mainSections }}
|
||||
{{ end }}
|
||||
|
||||
{{ if .Site.Params.excerpts }}
|
||||
|
||||
{{- range $Pages }}
|
||||
<article>
|
||||
<header>
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ if .Date }}<time datetime="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">{{ .Date.Format "January 02, 2006" }}</time>{{ end }}
|
||||
</header>
|
||||
{{ .Summary }}
|
||||
{{- if .Truncated }}
|
||||
<div class="more"><a href="{{ .RelPermalink }}">read more</a></div>
|
||||
{{- end }}
|
||||
</article>
|
||||
{{- end }}
|
||||
|
||||
{{ else }}
|
||||
|
||||
<article>
|
||||
<header><h1>{{ .Title | default "Posts" | humanize }}</h1></header>
|
||||
<ul>
|
||||
<ul class="archive">
|
||||
{{- range $Pages }}
|
||||
<li style="font-size: 1.1em;">
|
||||
{{ if .Date }}<time datetime="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}" style="display: inline-block; min-width: 10ch; margin: 0 .2em;">{{ .Date.Format "2006-01-02" }}</time>{{ end }}
|
||||
<li>
|
||||
{{ if .Date }}<time datetime="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">{{ .Date.Format "2006-01-02" }}</time>{{ end }}
|
||||
<a href="{{ .Permalink }}">{{ .Title }}</a>
|
||||
</li>
|
||||
{{- end }}
|
||||
@ -20,3 +37,5 @@
|
||||
</article>
|
||||
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
@ -1,3 +0,0 @@
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous">
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js" integrity="sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4" crossorigin="anonymous"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js" integrity="sha384-mll67QQFJfxn0IYznZYonOWZ644AWYC+Pt2cHqMaRhXVrursRwvLnLaebdGIlYNa" crossorigin="anonymous" onload="renderMathInElement(document.body);"></script>
|
@ -1,70 +1,79 @@
|
||||
@media (min-width: 50em) {
|
||||
@font-face {
|
||||
font-family: 'PT Sans';
|
||||
font-family: "PT Sans";
|
||||
src: local("PT Sans"), local("PTSans-Regular"), url("../fonts/PTSans-Regular.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'PT Sans';
|
||||
font-family: "PT Sans";
|
||||
src: local("PT Sans Bold"), local("PTSans-Bold"), url("../fonts/PTSans-Bold.woff") format("woff");
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
background: #363846;
|
||||
background: #d3d4db;
|
||||
font-size: 16px;
|
||||
font-size: calc(0.8rem + 0.3vw);
|
||||
padding: 0 calc(38% - 20em);
|
||||
padding: 0 calc(38% - 21em);
|
||||
}
|
||||
|
||||
body {
|
||||
background: #ffffff;
|
||||
color: #212228;
|
||||
font-family: "PT Sans", -apple-system, "Helvetica Neue", "Segoe UI", "Roboto", sans-serif;
|
||||
font-weight: 400;
|
||||
background: #ffffff;
|
||||
color: #17181e;
|
||||
box-shadow: 0 0 0 1px rgba(54, 56, 70, 0.6);
|
||||
margin: 0;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
box-shadow: 0 0 0.3em #c5c7cf;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
b, strong, th {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
p {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #68f;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
article a {
|
||||
color: #68f;
|
||||
header a, footer a, aside a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
header time {
|
||||
color: #8e8e91;
|
||||
color: #909194;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid rgba(139, 140, 143, 0.3);
|
||||
border: 1px solid rgba(144, 145, 148, 0.3);
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
article:not(:last-of-type) {
|
||||
border-bottom: 1.5px solid rgba(144, 145, 148, 0.2);
|
||||
}
|
||||
|
||||
blockquote {
|
||||
background: rgba(139, 140, 143, 0.06);
|
||||
border-left: 3px solid rgba(139, 140, 143, 0.9);
|
||||
background: rgba(144, 145, 148, 0.06);
|
||||
border-left: 3px solid rgba(144, 145, 148, 0.9);
|
||||
padding: 1px 1.5em;
|
||||
opacity: .75;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
blockquote, figure {
|
||||
@ -72,7 +81,7 @@ blockquote, figure {
|
||||
}
|
||||
|
||||
img, li {
|
||||
margin: .5em 0;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
img {
|
||||
@ -82,51 +91,52 @@ img {
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
overflow-y: scroll;
|
||||
border-spacing: 1px;
|
||||
box-shadow: 0 0 0 1px rgba(139, 140, 143, 0.12) inset;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 0 0 1px rgba(144, 145, 148, 0.12) inset;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: .5em 1em;
|
||||
box-shadow: 0 0 0 1px rgba(139, 140, 143, 0.12);
|
||||
padding: 0.5em 1em;
|
||||
box-shadow: 0 0 0 1px rgba(144, 145, 148, 0.12);
|
||||
}
|
||||
|
||||
tr:hover, tr:nth-child(odd) td {
|
||||
background: rgba(139, 140, 143, 0.04);
|
||||
background: rgba(144, 145, 148, 0.04);
|
||||
}
|
||||
|
||||
pre {
|
||||
background: rgba(34, 36, 44, 0.9)!important;
|
||||
color: #ffffff;
|
||||
background: rgba(144, 145, 148, 0.12);
|
||||
border-radius: 2px;
|
||||
font-size: .8em;
|
||||
font-size: 0.8em;
|
||||
margin: 1.5em 0;
|
||||
padding: .8em 1.2em;
|
||||
padding: 0.8em 1.2em;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code {
|
||||
font-size: .9em;
|
||||
background: rgba(139, 140, 143, 0.15);
|
||||
opacity: .7;
|
||||
font-size: 0.9em;
|
||||
background: rgba(144, 145, 148, 0.15);
|
||||
opacity: 0.7;
|
||||
border-radius: 2px;
|
||||
margin: 0 .1em;
|
||||
padding: .2em .4em;
|
||||
margin: 0 0.1em;
|
||||
padding: 0.2em 0.4em;
|
||||
}
|
||||
|
||||
body > header {
|
||||
body > header, body > footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: #17181e;
|
||||
justify-content: space-between;
|
||||
background: #2d2e36;
|
||||
color: #ffffff;
|
||||
border-bottom: 1px solid rgba(54, 56, 70, 0.6);
|
||||
}
|
||||
|
||||
body > header > a {
|
||||
font-size: 1.4em;
|
||||
body > header, body > article, body > footer {
|
||||
padding: 1.5em;
|
||||
}
|
||||
|
||||
article header {
|
||||
@ -134,31 +144,69 @@ article header {
|
||||
}
|
||||
|
||||
article header h1 {
|
||||
font-size: 1.8em;
|
||||
margin: 0 0 .1em;
|
||||
font-size: 1.7em;
|
||||
margin: 0 0 0.1em;
|
||||
}
|
||||
|
||||
nav {
|
||||
margin: .5em -.8em;
|
||||
margin: 0.5em -1em;
|
||||
}
|
||||
|
||||
nav a {
|
||||
margin: .5em .8em;
|
||||
}
|
||||
|
||||
body > header, body > article, body > footer {
|
||||
padding: 1.5em;
|
||||
}
|
||||
|
||||
@media (min-width: 40em) {
|
||||
body > header, body > article, body > footer {
|
||||
padding: 1.65em calc(20% - 4em);
|
||||
}
|
||||
margin: 0.5em 1em;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html, body {
|
||||
background: #17181e;
|
||||
html, body, body > header, body > footer {
|
||||
background: #212228;
|
||||
color: #ffffff;
|
||||
box-shadow: 0 0 0 1px #33353e;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 32em) {
|
||||
body > header, body > article, body > footer {
|
||||
padding: 1.65em calc(22% - 6em);
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.more {
|
||||
margin: 2em 0 1em;
|
||||
}
|
||||
|
||||
.more a {
|
||||
border-radius: 2px;
|
||||
border: 1.5px solid #68f;
|
||||
padding: 0.4em 0.8em;
|
||||
transition: 0.2s background, 0.2s color;
|
||||
}
|
||||
|
||||
.more a:hover {
|
||||
color: #fff;
|
||||
background: #68f;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.archive {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.archive time {
|
||||
display: inline-block;
|
||||
min-width: 10ch;
|
||||
margin: 0 0.2em;
|
||||
}
|
||||
|
||||
.highlight pre {
|
||||
background: rgba(47, 48, 57, 0.9)!important;
|
||||
color: white!important;
|
||||
}
|
||||
|
||||
.katex {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
216
static/css/minimal.css
Normal file
216
static/css/minimal.css
Normal file
@ -0,0 +1,216 @@
|
||||
@font-face {
|
||||
font-family: "PT Sans";
|
||||
src: local("PT Sans"), local("PTSans-Regular"), url("../fonts/PTSans-Regular.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "PT Sans";
|
||||
src: local("PT Sans Bold"), local("PTSans-Bold"), url("../fonts/PTSans-Bold.woff") format("woff");
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 16px;
|
||||
font-size: calc(0.8rem + 0.3vw);
|
||||
}
|
||||
|
||||
body {
|
||||
background: #ffffff;
|
||||
color: #212228;
|
||||
font-family: "PT Sans", -apple-system, "Helvetica Neue", "Segoe UI", "Roboto", sans-serif;
|
||||
font-weight: 400;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: #212228;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
b, strong, th {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #68f;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
header a, footer a, aside a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
header time {
|
||||
color: #909194;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid rgba(144, 145, 148, 0.3);
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
article:not(:last-of-type) {
|
||||
border-bottom: 1.5px solid rgba(144, 145, 148, 0.2);
|
||||
}
|
||||
|
||||
blockquote {
|
||||
background: rgba(144, 145, 148, 0.06);
|
||||
border-left: 3px solid rgba(144, 145, 148, 0.9);
|
||||
padding: 1px 1.5em;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
blockquote, figure {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
img, li {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 2px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
table {
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
overflow-y: scroll;
|
||||
border-spacing: 1px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 0 0 1px rgba(144, 145, 148, 0.12) inset;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 0.5em 1em;
|
||||
box-shadow: 0 0 0 1px rgba(144, 145, 148, 0.12);
|
||||
}
|
||||
|
||||
tr:hover, tr:nth-child(odd) td {
|
||||
background: rgba(144, 145, 148, 0.04);
|
||||
}
|
||||
|
||||
pre {
|
||||
background: rgba(144, 145, 148, 0.12);
|
||||
border-radius: 2px;
|
||||
font-size: 0.8em;
|
||||
margin: 1.5em 0;
|
||||
padding: 0.8em 1.2em;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code {
|
||||
font-size: 0.9em;
|
||||
background: rgba(144, 145, 148, 0.15);
|
||||
opacity: 0.7;
|
||||
border-radius: 2px;
|
||||
margin: 0 0.1em;
|
||||
padding: 0.2em 0.4em;
|
||||
}
|
||||
|
||||
body > header, body > footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
body > header, body > article, body > footer {
|
||||
padding: 1.5em;
|
||||
}
|
||||
|
||||
article header {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
article header h1 {
|
||||
font-size: 1.7em;
|
||||
margin: 0 0 0.1em;
|
||||
}
|
||||
|
||||
nav {
|
||||
margin: 0.5em -1em;
|
||||
}
|
||||
|
||||
nav a {
|
||||
margin: 0.5em 1em;
|
||||
}
|
||||
|
||||
body > header {
|
||||
box-shadow: 0 0 .6em rgba(33, 34, 40 ,0.04);
|
||||
border-bottom: 1px solid rgba(144, 145, 148, 0.14);
|
||||
}
|
||||
|
||||
body > footer {
|
||||
box-shadow: 0 0 .6em rgba(33, 34, 40 ,0.04) inset;
|
||||
border-top: 1px solid rgba(144, 145, 148, 0.14);
|
||||
}
|
||||
|
||||
@media (min-width: 38em) {
|
||||
body > header, body > article, body > footer {
|
||||
padding: 1.7em calc(38% - 14em);
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.more {
|
||||
margin: 2em 0 1em;
|
||||
}
|
||||
|
||||
.more a {
|
||||
border-radius: 2px;
|
||||
border: 1.5px solid #68f;
|
||||
padding: 0.4em 0.8em;
|
||||
transition: 0.2s background, 0.2s color;
|
||||
}
|
||||
|
||||
.more a:hover {
|
||||
color: #fff;
|
||||
background: #68f;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.archive {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.archive time {
|
||||
display: inline-block;
|
||||
min-width: 10ch;
|
||||
margin: 0 0.2em;
|
||||
}
|
||||
|
||||
.highlight pre {
|
||||
background: rgba(47, 48, 57, 0.9)!important;
|
||||
color: white!important;
|
||||
}
|
||||
|
||||
.katex {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
91
static/katex/README.md
Normal file
91
static/katex/README.md
Normal file
@ -0,0 +1,91 @@
|
||||
# [<img src="https://katex.org/img/katex-logo-black.svg" width="130" alt="KaTeX">](https://katex.org/)
|
||||
[![npm](https://img.shields.io/npm/v/katex.svg)](https://www.npmjs.com/package/katex)
|
||||
[![CI](https://github.com/KaTeX/KaTeX/workflows/CI/badge.svg?branch=master&event=push)](https://github.com/KaTeX/KaTeX/actions?query=workflow%3ACI)
|
||||
[![codecov](https://codecov.io/gh/KaTeX/KaTeX/branch/master/graph/badge.svg)](https://codecov.io/gh/KaTeX/KaTeX)
|
||||
[![Discussions](https://img.shields.io/badge/Discussions-join-brightgreen)](https://github.com/KaTeX/KaTeX/discussions)
|
||||
[![jsDelivr](https://data.jsdelivr.com/v1/package/npm/katex/badge?style=rounded)](https://www.jsdelivr.com/package/npm/katex)
|
||||
![katex.min.js size](https://img.badgesize.io/https://unpkg.com/katex/dist/katex.min.js?compression=gzip)
|
||||
[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/KaTeX/KaTeX)
|
||||
|
||||
KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
|
||||
|
||||
* **Fast:** KaTeX renders its math synchronously and doesn't need to reflow the page. See how it compares to a competitor in [this speed test](http://www.intmath.com/cg5/katex-mathjax-comparison.php).
|
||||
* **Print quality:** KaTeX's layout is based on Donald Knuth's TeX, the gold standard for math typesetting.
|
||||
* **Self contained:** KaTeX has no dependencies and can easily be bundled with your website resources.
|
||||
* **Server side rendering:** KaTeX produces the same output regardless of browser or environment, so you can pre-render expressions using Node.js and send them as plain HTML.
|
||||
|
||||
KaTeX is compatible with all major browsers, including Chrome, Safari, Firefox, Opera, Edge, and IE 11.
|
||||
|
||||
KaTeX supports much (but not all) of LaTeX and many LaTeX packages. See the [list of supported functions](https://katex.org/docs/supported.html).
|
||||
|
||||
Try out KaTeX [on the demo page](https://katex.org/#demo)!
|
||||
|
||||
## Getting started
|
||||
|
||||
### Starter template
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/katex.min.css" integrity="sha384-t5CR+zwDAROtph0PXGte6ia8heboACF9R5l/DiY+WZ3P2lxNgvJkQk5n7GPvLMYw" crossorigin="anonymous">
|
||||
|
||||
<!-- The loading of KaTeX is deferred to speed up page rendering -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/katex.min.js" integrity="sha384-FaFLTlohFghEIZkw6VGwmf9ISTubWAVYW8tG8+w2LAIftJEULZABrF9PPFv+tVkH" crossorigin="anonymous"></script>
|
||||
|
||||
<!-- To automatically render math in text elements, include the auto-render extension: -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/contrib/auto-render.min.js" integrity="sha384-bHBqxz8fokvgoJ/sc17HODNxa42TlaEhB+w8ZJXTc2nZf1VgEaFZeZvT4Mznfz0v" crossorigin="anonymous"
|
||||
onload="renderMathInElement(document.body);"></script>
|
||||
</head>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
You can also [download KaTeX](https://github.com/KaTeX/KaTeX/releases) and host it yourself.
|
||||
|
||||
For details on how to configure auto-render extension, refer to [the documentation](https://katex.org/docs/autorender.html).
|
||||
|
||||
### API
|
||||
|
||||
Call `katex.render` to render a TeX expression directly into a DOM element.
|
||||
For example:
|
||||
|
||||
```js
|
||||
katex.render("c = \\pm\\sqrt{a^2 + b^2}", element, {
|
||||
throwOnError: false
|
||||
});
|
||||
```
|
||||
|
||||
Call `katex.renderToString` to generate an HTML string of the rendered math,
|
||||
e.g., for server-side rendering. For example:
|
||||
|
||||
```js
|
||||
var html = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}", {
|
||||
throwOnError: false
|
||||
});
|
||||
// '<span class="katex">...</span>'
|
||||
```
|
||||
|
||||
Make sure to include the CSS and font files in both cases.
|
||||
If you are doing all rendering on the server, there is no need to include the
|
||||
JavaScript on the client.
|
||||
|
||||
The examples above use the `throwOnError: false` option, which renders invalid
|
||||
inputs as the TeX source code in red (by default), with the error message as
|
||||
hover text. For other available options, see the
|
||||
[API documentation](https://katex.org/docs/api.html),
|
||||
[options documentation](https://katex.org/docs/options.html), and
|
||||
[handling errors documentation](https://katex.org/docs/error.html).
|
||||
|
||||
## Demo and Documentation
|
||||
|
||||
Learn more about using KaTeX [on the website](https://katex.org)!
|
||||
|
||||
## Contributing
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
||||
|
||||
## License
|
||||
|
||||
KaTeX is licensed under the [MIT License](http://opensource.org/licenses/MIT).
|
326
static/katex/contrib/auto-render.js
Normal file
326
static/katex/contrib/auto-render.js
Normal file
@ -0,0 +1,326 @@
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory(require("katex"));
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define(["katex"], factory);
|
||||
else if(typeof exports === 'object')
|
||||
exports["renderMathInElement"] = factory(require("katex"));
|
||||
else
|
||||
root["renderMathInElement"] = factory(root["katex"]);
|
||||
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__974__) {
|
||||
return /******/ (function() { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 974:
|
||||
/***/ (function(module) {
|
||||
|
||||
module.exports = __WEBPACK_EXTERNAL_MODULE__974__;
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(__webpack_module_cache__[moduleId]) {
|
||||
/******/ return __webpack_module_cache__[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/compat get default export */
|
||||
/******/ !function() {
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function() { return module['default']; } :
|
||||
/******/ function() { return module; };
|
||||
/******/ __webpack_require__.d(getter, { a: getter });
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/define property getters */
|
||||
/******/ !function() {
|
||||
/******/ // define getter functions for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, definition) {
|
||||
/******/ for(var key in definition) {
|
||||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
|
||||
/******/ }();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
var __webpack_exports__ = {};
|
||||
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
|
||||
!function() {
|
||||
|
||||
// EXPORTS
|
||||
__webpack_require__.d(__webpack_exports__, {
|
||||
"default": function() { return /* binding */ auto_render; }
|
||||
});
|
||||
|
||||
// EXTERNAL MODULE: external "katex"
|
||||
var external_katex_ = __webpack_require__(974);
|
||||
var external_katex_default = /*#__PURE__*/__webpack_require__.n(external_katex_);
|
||||
;// CONCATENATED MODULE: ./contrib/auto-render/splitAtDelimiters.js
|
||||
/* eslint no-constant-condition:0 */
|
||||
var findEndOfMath = function findEndOfMath(delimiter, text, startIndex) {
|
||||
// Adapted from
|
||||
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
|
||||
var index = startIndex;
|
||||
var braceLevel = 0;
|
||||
var delimLength = delimiter.length;
|
||||
|
||||
while (index < text.length) {
|
||||
var character = text[index];
|
||||
|
||||
if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) {
|
||||
return index;
|
||||
} else if (character === "\\") {
|
||||
index++;
|
||||
} else if (character === "{") {
|
||||
braceLevel++;
|
||||
} else if (character === "}") {
|
||||
braceLevel--;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
var escapeRegex = function escapeRegex(string) {
|
||||
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
||||
};
|
||||
|
||||
var amsRegex = /^\\begin{/;
|
||||
|
||||
var splitAtDelimiters = function splitAtDelimiters(text, delimiters) {
|
||||
var index;
|
||||
var data = [];
|
||||
var regexLeft = new RegExp("(" + delimiters.map(function (x) {
|
||||
return escapeRegex(x.left);
|
||||
}).join("|") + ")");
|
||||
|
||||
while (true) {
|
||||
index = text.search(regexLeft);
|
||||
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (index > 0) {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text.slice(0, index)
|
||||
});
|
||||
text = text.slice(index); // now text starts with delimiter
|
||||
} // ... so this always succeeds:
|
||||
|
||||
|
||||
var i = delimiters.findIndex(function (delim) {
|
||||
return text.startsWith(delim.left);
|
||||
});
|
||||
index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
|
||||
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
var rawData = text.slice(0, index + delimiters[i].right.length);
|
||||
var math = amsRegex.test(rawData) ? rawData : text.slice(delimiters[i].left.length, index);
|
||||
data.push({
|
||||
type: "math",
|
||||
data: math,
|
||||
rawData: rawData,
|
||||
display: delimiters[i].display
|
||||
});
|
||||
text = text.slice(index + delimiters[i].right.length);
|
||||
}
|
||||
|
||||
if (text !== "") {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/* harmony default export */ var auto_render_splitAtDelimiters = (splitAtDelimiters);
|
||||
;// CONCATENATED MODULE: ./contrib/auto-render/auto-render.js
|
||||
/* eslint no-console:0 */
|
||||
|
||||
|
||||
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
|
||||
* API, we should copy it before mutating.
|
||||
*/
|
||||
|
||||
var renderMathInText = function renderMathInText(text, optionsCopy) {
|
||||
var data = auto_render_splitAtDelimiters(text, optionsCopy.delimiters);
|
||||
|
||||
if (data.length === 1 && data[0].type === 'text') {
|
||||
// There is no formula in the text.
|
||||
// Let's return null which means there is no need to replace
|
||||
// the current text node with a new one.
|
||||
return null;
|
||||
}
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (data[i].type === "text") {
|
||||
fragment.appendChild(document.createTextNode(data[i].data));
|
||||
} else {
|
||||
var span = document.createElement("span");
|
||||
var math = data[i].data; // Override any display mode defined in the settings with that
|
||||
// defined by the text itself
|
||||
|
||||
optionsCopy.displayMode = data[i].display;
|
||||
|
||||
try {
|
||||
if (optionsCopy.preProcess) {
|
||||
math = optionsCopy.preProcess(math);
|
||||
}
|
||||
|
||||
external_katex_default().render(math, span, optionsCopy);
|
||||
} catch (e) {
|
||||
if (!(e instanceof (external_katex_default()).ParseError)) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
optionsCopy.errorCallback("KaTeX auto-render: Failed to parse `" + data[i].data + "` with ", e);
|
||||
fragment.appendChild(document.createTextNode(data[i].rawData));
|
||||
continue;
|
||||
}
|
||||
|
||||
fragment.appendChild(span);
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
var renderElem = function renderElem(elem, optionsCopy) {
|
||||
for (var i = 0; i < elem.childNodes.length; i++) {
|
||||
var childNode = elem.childNodes[i];
|
||||
|
||||
if (childNode.nodeType === 3) {
|
||||
// Text node
|
||||
var frag = renderMathInText(childNode.textContent, optionsCopy);
|
||||
|
||||
if (frag) {
|
||||
i += frag.childNodes.length - 1;
|
||||
elem.replaceChild(frag, childNode);
|
||||
}
|
||||
} else if (childNode.nodeType === 1) {
|
||||
(function () {
|
||||
// Element node
|
||||
var className = ' ' + childNode.className + ' ';
|
||||
var shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(function (x) {
|
||||
return className.indexOf(' ' + x + ' ') === -1;
|
||||
});
|
||||
|
||||
if (shouldRender) {
|
||||
renderElem(childNode, optionsCopy);
|
||||
}
|
||||
})();
|
||||
} // Otherwise, it's something else, and ignore it.
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
var renderMathInElement = function renderMathInElement(elem, options) {
|
||||
if (!elem) {
|
||||
throw new Error("No element provided to render");
|
||||
}
|
||||
|
||||
var optionsCopy = {}; // Object.assign(optionsCopy, option)
|
||||
|
||||
for (var option in options) {
|
||||
if (options.hasOwnProperty(option)) {
|
||||
optionsCopy[option] = options[option];
|
||||
}
|
||||
} // default options
|
||||
|
||||
|
||||
optionsCopy.delimiters = optionsCopy.delimiters || [{
|
||||
left: "$$",
|
||||
right: "$$",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\(",
|
||||
right: "\\)",
|
||||
display: false
|
||||
}, // LaTeX uses $…$, but it ruins the display of normal `$` in text:
|
||||
// {left: "$", right: "$", display: false},
|
||||
// $ must come after $$
|
||||
// Render AMS environments even if outside $$…$$ delimiters.
|
||||
{
|
||||
left: "\\begin{equation}",
|
||||
right: "\\end{equation}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{align}",
|
||||
right: "\\end{align}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{alignat}",
|
||||
right: "\\end{alignat}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{gather}",
|
||||
right: "\\end{gather}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{CD}",
|
||||
right: "\\end{CD}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\[",
|
||||
right: "\\]",
|
||||
display: true
|
||||
}];
|
||||
optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
|
||||
optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
|
||||
optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
|
||||
// math elements within a single call to `renderMathInElement`.
|
||||
|
||||
optionsCopy.macros = optionsCopy.macros || {};
|
||||
renderElem(elem, optionsCopy);
|
||||
};
|
||||
|
||||
/* harmony default export */ var auto_render = (renderMathInElement);
|
||||
}();
|
||||
__webpack_exports__ = __webpack_exports__.default;
|
||||
/******/ return __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
});
|
1
static/katex/contrib/auto-render.min.js
vendored
Normal file
1
static/katex/contrib/auto-render.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={974:function(t){t.exports=e}},r={};function n(e){if(r[e])return r[e].exports;var a=r[e]={exports:{}};return t[e](a,a.exports,n),a.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var a={};return function(){n.d(a,{default:function(){return s}});var e=n(974),t=n.n(e),r=function(e,t,r){for(var n=r,a=0,i=e.length;n<t.length;){var o=t[n];if(a<=0&&t.slice(n,n+i)===e)return n;"\\"===o?n++:"{"===o?a++:"}"===o&&a--,n++}return-1},i=/^\\begin{/,o=function(e,t){for(var n,a=[],o=new RegExp("("+t.map((function(e){return e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")})).join("|")+")");-1!==(n=e.search(o));){n>0&&(a.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=i.test(d)?d:e.slice(t[l].left.length,n);a.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&a.push({type:"text",data:e}),a},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var a=document.createDocumentFragment(),i=0;i<n.length;i++)if("text"===n[i].type)a.appendChild(document.createTextNode(n[i].data));else{var l=document.createElement("span"),d=n[i].data;r.displayMode=n[i].display;try{r.preProcess&&(d=r.preProcess(d)),t().render(d,l,r)}catch(e){if(!(e instanceof t().ParseError))throw e;r.errorCallback("KaTeX auto-render: Failed to parse `"+n[i].data+"` with ",e),a.appendChild(document.createTextNode(n[i].rawData));continue}a.appendChild(l)}return a},d=function e(t,r){for(var n=0;n<t.childNodes.length;n++){var a=t.childNodes[n];if(3===a.nodeType){var i=l(a.textContent,r);i&&(n+=i.childNodes.length-1,t.replaceChild(i,a))}else 1===a.nodeType&&function(){var t=" "+a.className+" ";-1===r.ignoredTags.indexOf(a.nodeName.toLowerCase())&&r.ignoredClasses.every((function(e){return-1===t.indexOf(" "+e+" ")}))&&e(a,r)}()}},s=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code","option"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},d(e,r)}}(),a=a.default}()}));
|
222
static/katex/contrib/auto-render.mjs
Normal file
222
static/katex/contrib/auto-render.mjs
Normal file
@ -0,0 +1,222 @@
|
||||
import katex from '../katex.mjs';
|
||||
|
||||
/* eslint no-constant-condition:0 */
|
||||
var findEndOfMath = function findEndOfMath(delimiter, text, startIndex) {
|
||||
// Adapted from
|
||||
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
|
||||
var index = startIndex;
|
||||
var braceLevel = 0;
|
||||
var delimLength = delimiter.length;
|
||||
|
||||
while (index < text.length) {
|
||||
var character = text[index];
|
||||
|
||||
if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) {
|
||||
return index;
|
||||
} else if (character === "\\") {
|
||||
index++;
|
||||
} else if (character === "{") {
|
||||
braceLevel++;
|
||||
} else if (character === "}") {
|
||||
braceLevel--;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
var escapeRegex = function escapeRegex(string) {
|
||||
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
||||
};
|
||||
|
||||
var amsRegex = /^\\begin{/;
|
||||
|
||||
var splitAtDelimiters = function splitAtDelimiters(text, delimiters) {
|
||||
var index;
|
||||
var data = [];
|
||||
var regexLeft = new RegExp("(" + delimiters.map(x => escapeRegex(x.left)).join("|") + ")");
|
||||
|
||||
while (true) {
|
||||
index = text.search(regexLeft);
|
||||
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (index > 0) {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text.slice(0, index)
|
||||
});
|
||||
text = text.slice(index); // now text starts with delimiter
|
||||
} // ... so this always succeeds:
|
||||
|
||||
|
||||
var i = delimiters.findIndex(delim => text.startsWith(delim.left));
|
||||
index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
|
||||
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
var rawData = text.slice(0, index + delimiters[i].right.length);
|
||||
var math = amsRegex.test(rawData) ? rawData : text.slice(delimiters[i].left.length, index);
|
||||
data.push({
|
||||
type: "math",
|
||||
data: math,
|
||||
rawData,
|
||||
display: delimiters[i].display
|
||||
});
|
||||
text = text.slice(index + delimiters[i].right.length);
|
||||
}
|
||||
|
||||
if (text !== "") {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/* eslint no-console:0 */
|
||||
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
|
||||
* API, we should copy it before mutating.
|
||||
*/
|
||||
|
||||
var renderMathInText = function renderMathInText(text, optionsCopy) {
|
||||
var data = splitAtDelimiters(text, optionsCopy.delimiters);
|
||||
|
||||
if (data.length === 1 && data[0].type === 'text') {
|
||||
// There is no formula in the text.
|
||||
// Let's return null which means there is no need to replace
|
||||
// the current text node with a new one.
|
||||
return null;
|
||||
}
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (data[i].type === "text") {
|
||||
fragment.appendChild(document.createTextNode(data[i].data));
|
||||
} else {
|
||||
var span = document.createElement("span");
|
||||
var math = data[i].data; // Override any display mode defined in the settings with that
|
||||
// defined by the text itself
|
||||
|
||||
optionsCopy.displayMode = data[i].display;
|
||||
|
||||
try {
|
||||
if (optionsCopy.preProcess) {
|
||||
math = optionsCopy.preProcess(math);
|
||||
}
|
||||
|
||||
katex.render(math, span, optionsCopy);
|
||||
} catch (e) {
|
||||
if (!(e instanceof katex.ParseError)) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
optionsCopy.errorCallback("KaTeX auto-render: Failed to parse `" + data[i].data + "` with ", e);
|
||||
fragment.appendChild(document.createTextNode(data[i].rawData));
|
||||
continue;
|
||||
}
|
||||
|
||||
fragment.appendChild(span);
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
var renderElem = function renderElem(elem, optionsCopy) {
|
||||
for (var i = 0; i < elem.childNodes.length; i++) {
|
||||
var childNode = elem.childNodes[i];
|
||||
|
||||
if (childNode.nodeType === 3) {
|
||||
// Text node
|
||||
var frag = renderMathInText(childNode.textContent, optionsCopy);
|
||||
|
||||
if (frag) {
|
||||
i += frag.childNodes.length - 1;
|
||||
elem.replaceChild(frag, childNode);
|
||||
}
|
||||
} else if (childNode.nodeType === 1) {
|
||||
(function () {
|
||||
// Element node
|
||||
var className = ' ' + childNode.className + ' ';
|
||||
var shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(x => className.indexOf(' ' + x + ' ') === -1);
|
||||
|
||||
if (shouldRender) {
|
||||
renderElem(childNode, optionsCopy);
|
||||
}
|
||||
})();
|
||||
} // Otherwise, it's something else, and ignore it.
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
var renderMathInElement = function renderMathInElement(elem, options) {
|
||||
if (!elem) {
|
||||
throw new Error("No element provided to render");
|
||||
}
|
||||
|
||||
var optionsCopy = {}; // Object.assign(optionsCopy, option)
|
||||
|
||||
for (var option in options) {
|
||||
if (options.hasOwnProperty(option)) {
|
||||
optionsCopy[option] = options[option];
|
||||
}
|
||||
} // default options
|
||||
|
||||
|
||||
optionsCopy.delimiters = optionsCopy.delimiters || [{
|
||||
left: "$$",
|
||||
right: "$$",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\(",
|
||||
right: "\\)",
|
||||
display: false
|
||||
}, // LaTeX uses $…$, but it ruins the display of normal `$` in text:
|
||||
// {left: "$", right: "$", display: false},
|
||||
// $ must come after $$
|
||||
// Render AMS environments even if outside $$…$$ delimiters.
|
||||
{
|
||||
left: "\\begin{equation}",
|
||||
right: "\\end{equation}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{align}",
|
||||
right: "\\end{align}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{alignat}",
|
||||
right: "\\end{alignat}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{gather}",
|
||||
right: "\\end{gather}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{CD}",
|
||||
right: "\\end{CD}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\[",
|
||||
right: "\\]",
|
||||
display: true
|
||||
}];
|
||||
optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
|
||||
optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
|
||||
optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
|
||||
// math elements within a single call to `renderMathInElement`.
|
||||
|
||||
optionsCopy.macros = optionsCopy.macros || {};
|
||||
renderElem(elem, optionsCopy);
|
||||
};
|
||||
|
||||
export default renderMathInElement;
|
14
static/katex/contrib/copy-tex.css
Normal file
14
static/katex/contrib/copy-tex.css
Normal file
@ -0,0 +1,14 @@
|
||||
/* Force selection of entire .katex/.katex-display blocks, so that we can
|
||||
* copy/paste the entire source code. If you omit this CSS, partial
|
||||
* selections of a formula will work, but will copy the ugly HTML
|
||||
* representation instead of the LaTeX source code. (Full selections will
|
||||
* still produce the LaTeX source code.)
|
||||
*/
|
||||
.katex,
|
||||
.katex-display {
|
||||
-webkit-user-select: all;
|
||||
-moz-user-select: all;
|
||||
-ms-user-select: all;
|
||||
user-select: all;
|
||||
}
|
||||
|
116
static/katex/contrib/copy-tex.js
Normal file
116
static/katex/contrib/copy-tex.js
Normal file
@ -0,0 +1,116 @@
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory();
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define([], factory);
|
||||
else {
|
||||
var a = factory();
|
||||
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
|
||||
}
|
||||
})((typeof self !== 'undefined' ? self : this), function() {
|
||||
return /******/ (function() { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
var __webpack_exports__ = {};
|
||||
|
||||
;// CONCATENATED MODULE: ./contrib/copy-tex/katex2tex.js
|
||||
// Set these to how you want inline and display math to be delimited.
|
||||
var defaultCopyDelimiters = {
|
||||
inline: ['$', '$'],
|
||||
// alternative: ['\(', '\)']
|
||||
display: ['$$', '$$'] // alternative: ['\[', '\]']
|
||||
|
||||
}; // Replace .katex elements with their TeX source (<annotation> element).
|
||||
// Modifies fragment in-place. Useful for writing your own 'copy' handler,
|
||||
// as in copy-tex.js.
|
||||
|
||||
var katexReplaceWithTex = function katexReplaceWithTex(fragment, copyDelimiters) {
|
||||
if (copyDelimiters === void 0) {
|
||||
copyDelimiters = defaultCopyDelimiters;
|
||||
}
|
||||
|
||||
// Remove .katex-html blocks that are preceded by .katex-mathml blocks
|
||||
// (which will get replaced below).
|
||||
var katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');
|
||||
|
||||
for (var i = 0; i < katexHtml.length; i++) {
|
||||
var element = katexHtml[i];
|
||||
|
||||
if (element.remove) {
|
||||
element.remove(null);
|
||||
} else {
|
||||
element.parentNode.removeChild(element);
|
||||
}
|
||||
} // Replace .katex-mathml elements with their annotation (TeX source)
|
||||
// descendant, with inline delimiters.
|
||||
|
||||
|
||||
var katexMathml = fragment.querySelectorAll('.katex-mathml');
|
||||
|
||||
for (var _i = 0; _i < katexMathml.length; _i++) {
|
||||
var _element = katexMathml[_i];
|
||||
|
||||
var texSource = _element.querySelector('annotation');
|
||||
|
||||
if (texSource) {
|
||||
if (_element.replaceWith) {
|
||||
_element.replaceWith(texSource);
|
||||
} else {
|
||||
_element.parentNode.replaceChild(texSource, _element);
|
||||
}
|
||||
|
||||
texSource.innerHTML = copyDelimiters.inline[0] + texSource.innerHTML + copyDelimiters.inline[1];
|
||||
}
|
||||
} // Switch display math to display delimiters.
|
||||
|
||||
|
||||
var displays = fragment.querySelectorAll('.katex-display annotation');
|
||||
|
||||
for (var _i2 = 0; _i2 < displays.length; _i2++) {
|
||||
var _element2 = displays[_i2];
|
||||
_element2.innerHTML = copyDelimiters.display[0] + _element2.innerHTML.substr(copyDelimiters.inline[0].length, _element2.innerHTML.length - copyDelimiters.inline[0].length - copyDelimiters.inline[1].length) + copyDelimiters.display[1];
|
||||
}
|
||||
|
||||
return fragment;
|
||||
};
|
||||
/* harmony default export */ var katex2tex = (katexReplaceWithTex);
|
||||
;// CONCATENATED MODULE: ./contrib/copy-tex/copy-tex.js
|
||||
// Global copy handler to modify behavior on .katex elements.
|
||||
|
||||
document.addEventListener('copy', function (event) {
|
||||
var selection = window.getSelection();
|
||||
|
||||
if (selection.isCollapsed) {
|
||||
return; // default action OK if selection is empty
|
||||
}
|
||||
|
||||
var fragment = selection.getRangeAt(0).cloneContents();
|
||||
|
||||
if (!fragment.querySelector('.katex-mathml')) {
|
||||
return; // default action OK if no .katex-mathml elements
|
||||
} // Preserve usual HTML copy/paste behavior.
|
||||
|
||||
|
||||
var html = [];
|
||||
|
||||
for (var i = 0; i < fragment.childNodes.length; i++) {
|
||||
html.push(fragment.childNodes[i].outerHTML);
|
||||
}
|
||||
|
||||
event.clipboardData.setData('text/html', html.join('')); // Rewrite plain-text version.
|
||||
|
||||
event.clipboardData.setData('text/plain', katex2tex(fragment).textContent); // Prevent normal copy handling.
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
;// CONCATENATED MODULE: ./contrib/copy-tex/copy-tex.webpack.js
|
||||
/**
|
||||
* This is the webpack entry point for KaTeX. As ECMAScript doesn't support
|
||||
* CSS modules natively, a separate entry point is used.
|
||||
*/
|
||||
|
||||
|
||||
__webpack_exports__ = __webpack_exports__.default;
|
||||
/******/ return __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
});
|
1
static/katex/contrib/copy-tex.min.css
vendored
Normal file
1
static/katex/contrib/copy-tex.min.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.katex,.katex-display{-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all}
|
1
static/katex/contrib/copy-tex.min.js
vendored
Normal file
1
static/katex/contrib/copy-tex.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var l in n)("object"==typeof exports?exports:e)[l]=n[l]}}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={},t={inline:["$","$"],display:["$$","$$"]},n=function(e,n){void 0===n&&(n=t);for(var l=e.querySelectorAll(".katex-mathml + .katex-html"),r=0;r<l.length;r++){var i=l[r];i.remove?i.remove(null):i.parentNode.removeChild(i)}for(var o=e.querySelectorAll(".katex-mathml"),a=0;a<o.length;a++){var d=o[a],f=d.querySelector("annotation");f&&(d.replaceWith?d.replaceWith(f):d.parentNode.replaceChild(f,d),f.innerHTML=n.inline[0]+f.innerHTML+n.inline[1])}for(var c=e.querySelectorAll(".katex-display annotation"),s=0;s<c.length;s++){var p=c[s];p.innerHTML=n.display[0]+p.innerHTML.substr(n.inline[0].length,p.innerHTML.length-n.inline[0].length-n.inline[1].length)+n.display[1]}return e};return document.addEventListener("copy",(function(e){var t=window.getSelection();if(!t.isCollapsed){var l=t.getRangeAt(0).cloneContents();if(l.querySelector(".katex-mathml")){for(var r=[],i=0;i<l.childNodes.length;i++)r.push(l.childNodes[i].outerHTML);e.clipboardData.setData("text/html",r.join("")),e.clipboardData.setData("text/plain",n(l).textContent),e.preventDefault()}}})),e=e.default}()}));
|
86
static/katex/contrib/copy-tex.mjs
Normal file
86
static/katex/contrib/copy-tex.mjs
Normal file
@ -0,0 +1,86 @@
|
||||
// Set these to how you want inline and display math to be delimited.
|
||||
var defaultCopyDelimiters = {
|
||||
inline: ['$', '$'],
|
||||
// alternative: ['\(', '\)']
|
||||
display: ['$$', '$$'] // alternative: ['\[', '\]']
|
||||
|
||||
}; // Replace .katex elements with their TeX source (<annotation> element).
|
||||
// Modifies fragment in-place. Useful for writing your own 'copy' handler,
|
||||
// as in copy-tex.js.
|
||||
|
||||
var katexReplaceWithTex = function katexReplaceWithTex(fragment, copyDelimiters) {
|
||||
if (copyDelimiters === void 0) {
|
||||
copyDelimiters = defaultCopyDelimiters;
|
||||
}
|
||||
|
||||
// Remove .katex-html blocks that are preceded by .katex-mathml blocks
|
||||
// (which will get replaced below).
|
||||
var katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');
|
||||
|
||||
for (var i = 0; i < katexHtml.length; i++) {
|
||||
var element = katexHtml[i];
|
||||
|
||||
if (element.remove) {
|
||||
element.remove(null);
|
||||
} else {
|
||||
element.parentNode.removeChild(element);
|
||||
}
|
||||
} // Replace .katex-mathml elements with their annotation (TeX source)
|
||||
// descendant, with inline delimiters.
|
||||
|
||||
|
||||
var katexMathml = fragment.querySelectorAll('.katex-mathml');
|
||||
|
||||
for (var _i = 0; _i < katexMathml.length; _i++) {
|
||||
var _element = katexMathml[_i];
|
||||
|
||||
var texSource = _element.querySelector('annotation');
|
||||
|
||||
if (texSource) {
|
||||
if (_element.replaceWith) {
|
||||
_element.replaceWith(texSource);
|
||||
} else {
|
||||
_element.parentNode.replaceChild(texSource, _element);
|
||||
}
|
||||
|
||||
texSource.innerHTML = copyDelimiters.inline[0] + texSource.innerHTML + copyDelimiters.inline[1];
|
||||
}
|
||||
} // Switch display math to display delimiters.
|
||||
|
||||
|
||||
var displays = fragment.querySelectorAll('.katex-display annotation');
|
||||
|
||||
for (var _i2 = 0; _i2 < displays.length; _i2++) {
|
||||
var _element2 = displays[_i2];
|
||||
_element2.innerHTML = copyDelimiters.display[0] + _element2.innerHTML.substr(copyDelimiters.inline[0].length, _element2.innerHTML.length - copyDelimiters.inline[0].length - copyDelimiters.inline[1].length) + copyDelimiters.display[1];
|
||||
}
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
document.addEventListener('copy', function (event) {
|
||||
var selection = window.getSelection();
|
||||
|
||||
if (selection.isCollapsed) {
|
||||
return; // default action OK if selection is empty
|
||||
}
|
||||
|
||||
var fragment = selection.getRangeAt(0).cloneContents();
|
||||
|
||||
if (!fragment.querySelector('.katex-mathml')) {
|
||||
return; // default action OK if no .katex-mathml elements
|
||||
} // Preserve usual HTML copy/paste behavior.
|
||||
|
||||
|
||||
var html = [];
|
||||
|
||||
for (var i = 0; i < fragment.childNodes.length; i++) {
|
||||
html.push(fragment.childNodes[i].outerHTML);
|
||||
}
|
||||
|
||||
event.clipboardData.setData('text/html', html.join('')); // Rewrite plain-text version.
|
||||
|
||||
event.clipboardData.setData('text/plain', katexReplaceWithTex(fragment).textContent); // Prevent normal copy handling.
|
||||
|
||||
event.preventDefault();
|
||||
});
|
111
static/katex/contrib/mathtex-script-type.js
Normal file
111
static/katex/contrib/mathtex-script-type.js
Normal file
@ -0,0 +1,111 @@
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory(require("katex"));
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define(["katex"], factory);
|
||||
else {
|
||||
var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
|
||||
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
|
||||
}
|
||||
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__974__) {
|
||||
return /******/ (function() { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 974:
|
||||
/***/ (function(module) {
|
||||
|
||||
module.exports = __WEBPACK_EXTERNAL_MODULE__974__;
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(__webpack_module_cache__[moduleId]) {
|
||||
/******/ return __webpack_module_cache__[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/compat get default export */
|
||||
/******/ !function() {
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function() { return module['default']; } :
|
||||
/******/ function() { return module; };
|
||||
/******/ __webpack_require__.d(getter, { a: getter });
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/define property getters */
|
||||
/******/ !function() {
|
||||
/******/ // define getter functions for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, definition) {
|
||||
/******/ for(var key in definition) {
|
||||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
|
||||
/******/ }();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
var __webpack_exports__ = {};
|
||||
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
|
||||
!function() {
|
||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(974);
|
||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
|
||||
|
||||
var scripts = document.body.getElementsByTagName("script");
|
||||
scripts = Array.prototype.slice.call(scripts);
|
||||
scripts.forEach(function (script) {
|
||||
if (!script.type || !script.type.match(/math\/tex/i)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var display = script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null;
|
||||
var katexElement = document.createElement(display ? "div" : "span");
|
||||
katexElement.setAttribute("class", display ? "equation" : "inline-equation");
|
||||
|
||||
try {
|
||||
katex__WEBPACK_IMPORTED_MODULE_0___default().render(script.text, katexElement, {
|
||||
displayMode: display
|
||||
});
|
||||
} catch (err) {
|
||||
//console.error(err); linter doesn't like this
|
||||
katexElement.textContent = script.text;
|
||||
}
|
||||
|
||||
script.parentNode.replaceChild(katexElement, script);
|
||||
});
|
||||
}();
|
||||
__webpack_exports__ = __webpack_exports__.default;
|
||||
/******/ return __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
});
|
1
static/katex/contrib/mathtex-script-type.min.js
vendored
Normal file
1
static/katex/contrib/mathtex-script-type.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("katex"));else if("function"==typeof define&&define.amd)define(["katex"],t);else{var r="object"==typeof exports?t(require("katex")):t(e.katex);for(var n in r)("object"==typeof exports?exports:e)[n]=r[n]}}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={974:function(t){t.exports=e}},r={};function n(e){if(r[e])return r[e].exports;var o=r[e]={exports:{}};return t[e](o,o.exports,n),o.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o,i,a,u={};return o=n(974),i=n.n(o),a=document.body.getElementsByTagName("script"),(a=Array.prototype.slice.call(a)).forEach((function(e){if(!e.type||!e.type.match(/math\/tex/i))return-1;var t=null!=e.type.match(/mode\s*=\s*display(;|\s|\n|$)/),r=document.createElement(t?"div":"span");r.setAttribute("class",t?"equation":"inline-equation");try{i().render(e.text,r,{displayMode:t})}catch(t){r.textContent=e.text}e.parentNode.replaceChild(r,e)})),u=u.default}()}));
|
24
static/katex/contrib/mathtex-script-type.mjs
Normal file
24
static/katex/contrib/mathtex-script-type.mjs
Normal file
@ -0,0 +1,24 @@
|
||||
import katex from '../katex.mjs';
|
||||
|
||||
var scripts = document.body.getElementsByTagName("script");
|
||||
scripts = Array.prototype.slice.call(scripts);
|
||||
scripts.forEach(function (script) {
|
||||
if (!script.type || !script.type.match(/math\/tex/i)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var display = script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null;
|
||||
var katexElement = document.createElement(display ? "div" : "span");
|
||||
katexElement.setAttribute("class", display ? "equation" : "inline-equation");
|
||||
|
||||
try {
|
||||
katex.render(script.text, katexElement, {
|
||||
displayMode: display
|
||||
});
|
||||
} catch (err) {
|
||||
//console.error(err); linter doesn't like this
|
||||
katexElement.textContent = script.text;
|
||||
}
|
||||
|
||||
script.parentNode.replaceChild(katexElement, script);
|
||||
});
|
3215
static/katex/contrib/mhchem.js
Normal file
3215
static/katex/contrib/mhchem.js
Normal file
File diff suppressed because it is too large
Load Diff
1
static/katex/contrib/mhchem.min.js
vendored
Normal file
1
static/katex/contrib/mhchem.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
3109
static/katex/contrib/mhchem.mjs
Normal file
3109
static/katex/contrib/mhchem.mjs
Normal file
File diff suppressed because it is too large
Load Diff
874
static/katex/contrib/render-a11y-string.js
Normal file
874
static/katex/contrib/render-a11y-string.js
Normal file
@ -0,0 +1,874 @@
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory(require("katex"));
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define(["katex"], factory);
|
||||
else {
|
||||
var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
|
||||
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
|
||||
}
|
||||
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__974__) {
|
||||
return /******/ (function() { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 974:
|
||||
/***/ (function(module) {
|
||||
|
||||
module.exports = __WEBPACK_EXTERNAL_MODULE__974__;
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(__webpack_module_cache__[moduleId]) {
|
||||
/******/ return __webpack_module_cache__[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/compat get default export */
|
||||
/******/ !function() {
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function() { return module['default']; } :
|
||||
/******/ function() { return module; };
|
||||
/******/ __webpack_require__.d(getter, { a: getter });
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/define property getters */
|
||||
/******/ !function() {
|
||||
/******/ // define getter functions for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, definition) {
|
||||
/******/ for(var key in definition) {
|
||||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
|
||||
/******/ }();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
var __webpack_exports__ = {};
|
||||
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
|
||||
!function() {
|
||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(974);
|
||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
|
||||
/**
|
||||
* renderA11yString returns a readable string.
|
||||
*
|
||||
* In some cases the string will have the proper semantic math
|
||||
* meaning,:
|
||||
* renderA11yString("\\frac{1}{2}"")
|
||||
* -> "start fraction, 1, divided by, 2, end fraction"
|
||||
*
|
||||
* However, other cases do not:
|
||||
* renderA11yString("f(x) = x^2")
|
||||
* -> "f, left parenthesis, x, right parenthesis, equals, x, squared"
|
||||
*
|
||||
* The commas in the string aim to increase ease of understanding
|
||||
* when read by a screenreader.
|
||||
*/
|
||||
// NOTE: since we're importing types here these files won't actually be
|
||||
// included in the build.
|
||||
// $FlowIgnore: we import the types directly anyways
|
||||
|
||||
var stringMap = {
|
||||
"(": "left parenthesis",
|
||||
")": "right parenthesis",
|
||||
"[": "open bracket",
|
||||
"]": "close bracket",
|
||||
"\\{": "left brace",
|
||||
"\\}": "right brace",
|
||||
"\\lvert": "open vertical bar",
|
||||
"\\rvert": "close vertical bar",
|
||||
"|": "vertical bar",
|
||||
"\\uparrow": "up arrow",
|
||||
"\\Uparrow": "up arrow",
|
||||
"\\downarrow": "down arrow",
|
||||
"\\Downarrow": "down arrow",
|
||||
"\\updownarrow": "up down arrow",
|
||||
"\\leftarrow": "left arrow",
|
||||
"\\Leftarrow": "left arrow",
|
||||
"\\rightarrow": "right arrow",
|
||||
"\\Rightarrow": "right arrow",
|
||||
"\\langle": "open angle",
|
||||
"\\rangle": "close angle",
|
||||
"\\lfloor": "open floor",
|
||||
"\\rfloor": "close floor",
|
||||
"\\int": "integral",
|
||||
"\\intop": "integral",
|
||||
"\\lim": "limit",
|
||||
"\\ln": "natural log",
|
||||
"\\log": "log",
|
||||
"\\sin": "sine",
|
||||
"\\cos": "cosine",
|
||||
"\\tan": "tangent",
|
||||
"\\cot": "cotangent",
|
||||
"\\sum": "sum",
|
||||
"/": "slash",
|
||||
",": "comma",
|
||||
".": "point",
|
||||
"-": "negative",
|
||||
"+": "plus",
|
||||
"~": "tilde",
|
||||
":": "colon",
|
||||
"?": "question mark",
|
||||
"'": "apostrophe",
|
||||
"\\%": "percent",
|
||||
" ": "space",
|
||||
"\\ ": "space",
|
||||
"\\$": "dollar sign",
|
||||
"\\angle": "angle",
|
||||
"\\degree": "degree",
|
||||
"\\circ": "circle",
|
||||
"\\vec": "vector",
|
||||
"\\triangle": "triangle",
|
||||
"\\pi": "pi",
|
||||
"\\prime": "prime",
|
||||
"\\infty": "infinity",
|
||||
"\\alpha": "alpha",
|
||||
"\\beta": "beta",
|
||||
"\\gamma": "gamma",
|
||||
"\\omega": "omega",
|
||||
"\\theta": "theta",
|
||||
"\\sigma": "sigma",
|
||||
"\\lambda": "lambda",
|
||||
"\\tau": "tau",
|
||||
"\\Delta": "delta",
|
||||
"\\delta": "delta",
|
||||
"\\mu": "mu",
|
||||
"\\rho": "rho",
|
||||
"\\nabla": "del",
|
||||
"\\ell": "ell",
|
||||
"\\ldots": "dots",
|
||||
// TODO: add entries for all accents
|
||||
"\\hat": "hat",
|
||||
"\\acute": "acute"
|
||||
};
|
||||
var powerMap = {
|
||||
"prime": "prime",
|
||||
"degree": "degrees",
|
||||
"circle": "degrees",
|
||||
"2": "squared",
|
||||
"3": "cubed"
|
||||
};
|
||||
var openMap = {
|
||||
"|": "open vertical bar",
|
||||
".": ""
|
||||
};
|
||||
var closeMap = {
|
||||
"|": "close vertical bar",
|
||||
".": ""
|
||||
};
|
||||
var binMap = {
|
||||
"+": "plus",
|
||||
"-": "minus",
|
||||
"\\pm": "plus minus",
|
||||
"\\cdot": "dot",
|
||||
"*": "times",
|
||||
"/": "divided by",
|
||||
"\\times": "times",
|
||||
"\\div": "divided by",
|
||||
"\\circ": "circle",
|
||||
"\\bullet": "bullet"
|
||||
};
|
||||
var relMap = {
|
||||
"=": "equals",
|
||||
"\\approx": "approximately equals",
|
||||
"≠": "does not equal",
|
||||
"\\geq": "is greater than or equal to",
|
||||
"\\ge": "is greater than or equal to",
|
||||
"\\leq": "is less than or equal to",
|
||||
"\\le": "is less than or equal to",
|
||||
">": "is greater than",
|
||||
"<": "is less than",
|
||||
"\\leftarrow": "left arrow",
|
||||
"\\Leftarrow": "left arrow",
|
||||
"\\rightarrow": "right arrow",
|
||||
"\\Rightarrow": "right arrow",
|
||||
":": "colon"
|
||||
};
|
||||
var accentUnderMap = {
|
||||
"\\underleftarrow": "left arrow",
|
||||
"\\underrightarrow": "right arrow",
|
||||
"\\underleftrightarrow": "left-right arrow",
|
||||
"\\undergroup": "group",
|
||||
"\\underlinesegment": "line segment",
|
||||
"\\utilde": "tilde"
|
||||
};
|
||||
|
||||
var buildString = function buildString(str, type, a11yStrings) {
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
|
||||
var ret;
|
||||
|
||||
if (type === "open") {
|
||||
ret = str in openMap ? openMap[str] : stringMap[str] || str;
|
||||
} else if (type === "close") {
|
||||
ret = str in closeMap ? closeMap[str] : stringMap[str] || str;
|
||||
} else if (type === "bin") {
|
||||
ret = binMap[str] || str;
|
||||
} else if (type === "rel") {
|
||||
ret = relMap[str] || str;
|
||||
} else {
|
||||
ret = stringMap[str] || str;
|
||||
} // If the text to add is a number and there is already a string
|
||||
// in the list and the last string is a number then we should
|
||||
// combine them into a single number
|
||||
|
||||
|
||||
if (/^\d+$/.test(ret) && a11yStrings.length > 0 && // TODO(kevinb): check that the last item in a11yStrings is a string
|
||||
// I think we might be able to drop the nested arrays, which would make
|
||||
// this easier to type
|
||||
// $FlowFixMe
|
||||
/^\d+$/.test(a11yStrings[a11yStrings.length - 1])) {
|
||||
a11yStrings[a11yStrings.length - 1] += ret;
|
||||
} else if (ret) {
|
||||
a11yStrings.push(ret);
|
||||
}
|
||||
};
|
||||
|
||||
var buildRegion = function buildRegion(a11yStrings, callback) {
|
||||
var regionStrings = [];
|
||||
a11yStrings.push(regionStrings);
|
||||
callback(regionStrings);
|
||||
};
|
||||
|
||||
var handleObject = function handleObject(tree, a11yStrings, atomType) {
|
||||
// Everything else is assumed to be an object...
|
||||
switch (tree.type) {
|
||||
case "accent":
|
||||
{
|
||||
buildRegion(a11yStrings, function (a11yStrings) {
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
a11yStrings.push("with");
|
||||
buildString(tree.label, "normal", a11yStrings);
|
||||
a11yStrings.push("on top");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "accentUnder":
|
||||
{
|
||||
buildRegion(a11yStrings, function (a11yStrings) {
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
a11yStrings.push("with");
|
||||
buildString(accentUnderMap[tree.label], "normal", a11yStrings);
|
||||
a11yStrings.push("underneath");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "accent-token":
|
||||
{
|
||||
// Used internally by accent symbols.
|
||||
break;
|
||||
}
|
||||
|
||||
case "atom":
|
||||
{
|
||||
var text = tree.text;
|
||||
|
||||
switch (tree.family) {
|
||||
case "bin":
|
||||
{
|
||||
buildString(text, "bin", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "close":
|
||||
{
|
||||
buildString(text, "close", a11yStrings);
|
||||
break;
|
||||
}
|
||||
// TODO(kevinb): figure out what should be done for inner
|
||||
|
||||
case "inner":
|
||||
{
|
||||
buildString(tree.text, "inner", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "open":
|
||||
{
|
||||
buildString(text, "open", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "punct":
|
||||
{
|
||||
buildString(text, "punct", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "rel":
|
||||
{
|
||||
buildString(text, "rel", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
tree.family;
|
||||
throw new Error("\"" + tree.family + "\" is not a valid atom type");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "color":
|
||||
{
|
||||
var color = tree.color.replace(/katex-/, "");
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start color " + color);
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end color " + color);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "color-token":
|
||||
{
|
||||
// Used by \color, \colorbox, and \fcolorbox but not directly rendered.
|
||||
// It's a leaf node and has no children so just break.
|
||||
break;
|
||||
}
|
||||
|
||||
case "delimsizing":
|
||||
{
|
||||
if (tree.delim && tree.delim !== ".") {
|
||||
buildString(tree.delim, "normal", a11yStrings);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "genfrac":
|
||||
{
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
// genfrac can have unbalanced delimiters
|
||||
var leftDelim = tree.leftDelim,
|
||||
rightDelim = tree.rightDelim; // NOTE: Not sure if this is a safe assumption
|
||||
// hasBarLine true -> fraction, false -> binomial
|
||||
|
||||
if (tree.hasBarLine) {
|
||||
regionStrings.push("start fraction");
|
||||
leftDelim && buildString(leftDelim, "open", regionStrings);
|
||||
buildA11yStrings(tree.numer, regionStrings, atomType);
|
||||
regionStrings.push("divided by");
|
||||
buildA11yStrings(tree.denom, regionStrings, atomType);
|
||||
rightDelim && buildString(rightDelim, "close", regionStrings);
|
||||
regionStrings.push("end fraction");
|
||||
} else {
|
||||
regionStrings.push("start binomial");
|
||||
leftDelim && buildString(leftDelim, "open", regionStrings);
|
||||
buildA11yStrings(tree.numer, regionStrings, atomType);
|
||||
regionStrings.push("over");
|
||||
buildA11yStrings(tree.denom, regionStrings, atomType);
|
||||
rightDelim && buildString(rightDelim, "close", regionStrings);
|
||||
regionStrings.push("end binomial");
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "hbox":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "kern":
|
||||
{
|
||||
// No op: we don't attempt to present kerning information
|
||||
// to the screen reader.
|
||||
break;
|
||||
}
|
||||
|
||||
case "leftright":
|
||||
{
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
buildString(tree.left, "open", regionStrings);
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
buildString(tree.right, "close", regionStrings);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "leftright-right":
|
||||
{
|
||||
// TODO: double check that this is a no-op
|
||||
break;
|
||||
}
|
||||
|
||||
case "lap":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mathord":
|
||||
{
|
||||
buildString(tree.text, "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "op":
|
||||
{
|
||||
var body = tree.body,
|
||||
name = tree.name;
|
||||
|
||||
if (body) {
|
||||
buildA11yStrings(body, a11yStrings, atomType);
|
||||
} else if (name) {
|
||||
buildString(name, "normal", a11yStrings);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "op-token":
|
||||
{
|
||||
// Used internally by operator symbols.
|
||||
buildString(tree.text, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "ordgroup":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "overline":
|
||||
{
|
||||
buildRegion(a11yStrings, function (a11yStrings) {
|
||||
a11yStrings.push("start overline");
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
a11yStrings.push("end overline");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "phantom":
|
||||
{
|
||||
a11yStrings.push("empty space");
|
||||
break;
|
||||
}
|
||||
|
||||
case "raisebox":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "rule":
|
||||
{
|
||||
a11yStrings.push("rectangle");
|
||||
break;
|
||||
}
|
||||
|
||||
case "sizing":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "spacing":
|
||||
{
|
||||
a11yStrings.push("space");
|
||||
break;
|
||||
}
|
||||
|
||||
case "styling":
|
||||
{
|
||||
// We ignore the styling and just pass through the contents
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "sqrt":
|
||||
{
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
var body = tree.body,
|
||||
index = tree.index;
|
||||
|
||||
if (index) {
|
||||
var indexString = flatten(buildA11yStrings(index, [], atomType)).join(",");
|
||||
|
||||
if (indexString === "3") {
|
||||
regionStrings.push("cube root of");
|
||||
buildA11yStrings(body, regionStrings, atomType);
|
||||
regionStrings.push("end cube root");
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("root");
|
||||
regionStrings.push("start index");
|
||||
buildA11yStrings(index, regionStrings, atomType);
|
||||
regionStrings.push("end index");
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("square root of");
|
||||
buildA11yStrings(body, regionStrings, atomType);
|
||||
regionStrings.push("end square root");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "supsub":
|
||||
{
|
||||
var base = tree.base,
|
||||
sub = tree.sub,
|
||||
sup = tree.sup;
|
||||
var isLog = false;
|
||||
|
||||
if (base) {
|
||||
buildA11yStrings(base, a11yStrings, atomType);
|
||||
isLog = base.type === "op" && base.name === "\\log";
|
||||
}
|
||||
|
||||
if (sub) {
|
||||
var regionName = isLog ? "base" : "subscript";
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start " + regionName);
|
||||
buildA11yStrings(sub, regionStrings, atomType);
|
||||
regionStrings.push("end " + regionName);
|
||||
});
|
||||
}
|
||||
|
||||
if (sup) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
var supString = flatten(buildA11yStrings(sup, [], atomType)).join(",");
|
||||
|
||||
if (supString in powerMap) {
|
||||
regionStrings.push(powerMap[supString]);
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("start superscript");
|
||||
buildA11yStrings(sup, regionStrings, atomType);
|
||||
regionStrings.push("end superscript");
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "text":
|
||||
{
|
||||
// TODO: handle other fonts
|
||||
if (tree.font === "\\textbf") {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start bold text");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end bold text");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start text");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end text");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "textord":
|
||||
{
|
||||
buildString(tree.text, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "smash":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "enclose":
|
||||
{
|
||||
// TODO: create a map for these.
|
||||
// TODO: differentiate between a body with a single atom, e.g.
|
||||
// "cancel a" instead of "start cancel, a, end cancel"
|
||||
if (/cancel/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start cancel");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end cancel");
|
||||
});
|
||||
break;
|
||||
} else if (/box/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start box");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end box");
|
||||
});
|
||||
break;
|
||||
} else if (/sout/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start strikeout");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end strikeout");
|
||||
});
|
||||
break;
|
||||
} else if (/phase/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start phase angle");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end phase angle");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
throw new Error("KaTeX-a11y: enclose node with " + tree.label + " not supported yet");
|
||||
}
|
||||
|
||||
case "vcenter":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "vphantom":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: vphantom not implemented yet");
|
||||
}
|
||||
|
||||
case "hphantom":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: hphantom not implemented yet");
|
||||
}
|
||||
|
||||
case "operatorname":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "array":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: array not implemented yet");
|
||||
}
|
||||
|
||||
case "raw":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: raw not implemented yet");
|
||||
}
|
||||
|
||||
case "size":
|
||||
{
|
||||
// Although there are nodes of type "size" in the parse tree, they have
|
||||
// no semantic meaning and should be ignored.
|
||||
break;
|
||||
}
|
||||
|
||||
case "url":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: url not implemented yet");
|
||||
}
|
||||
|
||||
case "tag":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: tag not implemented yet");
|
||||
}
|
||||
|
||||
case "verb":
|
||||
{
|
||||
buildString("start verbatim", "normal", a11yStrings);
|
||||
buildString(tree.body, "normal", a11yStrings);
|
||||
buildString("end verbatim", "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "environment":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: environment not implemented yet");
|
||||
}
|
||||
|
||||
case "horizBrace":
|
||||
{
|
||||
buildString("start " + tree.label.slice(1), "normal", a11yStrings);
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
buildString("end " + tree.label.slice(1), "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "infix":
|
||||
{
|
||||
// All infix nodes are replace with other nodes.
|
||||
break;
|
||||
}
|
||||
|
||||
case "includegraphics":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: includegraphics not implemented yet");
|
||||
}
|
||||
|
||||
case "font":
|
||||
{
|
||||
// TODO: callout the start/end of specific fonts
|
||||
// TODO: map \BBb{N} to "the naturals" or something like that
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "href":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: href not implemented yet");
|
||||
}
|
||||
|
||||
case "cr":
|
||||
{
|
||||
// This is used by environments.
|
||||
throw new Error("KaTeX-a11y: cr not implemented yet");
|
||||
}
|
||||
|
||||
case "underline":
|
||||
{
|
||||
buildRegion(a11yStrings, function (a11yStrings) {
|
||||
a11yStrings.push("start underline");
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
a11yStrings.push("end underline");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "xArrow":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: xArrow not implemented yet");
|
||||
}
|
||||
|
||||
case "cdlabel":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: cdlabel not implemented yet");
|
||||
}
|
||||
|
||||
case "cdlabelparent":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");
|
||||
}
|
||||
|
||||
case "mclass":
|
||||
{
|
||||
// \neq and \ne are macros so we let "htmlmathml" render the mathmal
|
||||
// side of things and extract the text from that.
|
||||
var _atomType = tree.mclass.slice(1); // $FlowFixMe: drop the leading "m" from the values in mclass
|
||||
|
||||
|
||||
buildA11yStrings(tree.body, a11yStrings, _atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mathchoice":
|
||||
{
|
||||
// TODO: track which which style we're using, e.g. dispaly, text, etc.
|
||||
// default to text style if even that may not be the correct style
|
||||
buildA11yStrings(tree.text, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "htmlmathml":
|
||||
{
|
||||
buildA11yStrings(tree.mathml, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "middle":
|
||||
{
|
||||
buildString(tree.delim, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "internal":
|
||||
{
|
||||
// internal nodes are never included in the parse tree
|
||||
break;
|
||||
}
|
||||
|
||||
case "html":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
tree.type;
|
||||
throw new Error("KaTeX a11y un-recognized type: " + tree.type);
|
||||
}
|
||||
};
|
||||
|
||||
var buildA11yStrings = function buildA11yStrings(tree, a11yStrings, atomType) {
|
||||
if (a11yStrings === void 0) {
|
||||
a11yStrings = [];
|
||||
}
|
||||
|
||||
if (tree instanceof Array) {
|
||||
for (var i = 0; i < tree.length; i++) {
|
||||
buildA11yStrings(tree[i], a11yStrings, atomType);
|
||||
}
|
||||
} else {
|
||||
handleObject(tree, a11yStrings, atomType);
|
||||
}
|
||||
|
||||
return a11yStrings;
|
||||
};
|
||||
|
||||
var flatten = function flatten(array) {
|
||||
var result = [];
|
||||
array.forEach(function (item) {
|
||||
if (item instanceof Array) {
|
||||
result = result.concat(flatten(item));
|
||||
} else {
|
||||
result.push(item);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
var renderA11yString = function renderA11yString(text, settings) {
|
||||
var tree = katex__WEBPACK_IMPORTED_MODULE_0___default().__parse(text, settings);
|
||||
|
||||
var a11yStrings = buildA11yStrings(tree, [], "normal");
|
||||
return flatten(a11yStrings).join(", ");
|
||||
};
|
||||
|
||||
/* harmony default export */ __webpack_exports__["default"] = (renderA11yString);
|
||||
}();
|
||||
__webpack_exports__ = __webpack_exports__.default;
|
||||
/******/ return __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
});
|
1
static/katex/contrib/render-a11y-string.min.js
vendored
Normal file
1
static/katex/contrib/render-a11y-string.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
794
static/katex/contrib/render-a11y-string.mjs
Normal file
794
static/katex/contrib/render-a11y-string.mjs
Normal file
@ -0,0 +1,794 @@
|
||||
import katex from '../katex.mjs';
|
||||
|
||||
/**
|
||||
* renderA11yString returns a readable string.
|
||||
*
|
||||
* In some cases the string will have the proper semantic math
|
||||
* meaning,:
|
||||
* renderA11yString("\\frac{1}{2}"")
|
||||
* -> "start fraction, 1, divided by, 2, end fraction"
|
||||
*
|
||||
* However, other cases do not:
|
||||
* renderA11yString("f(x) = x^2")
|
||||
* -> "f, left parenthesis, x, right parenthesis, equals, x, squared"
|
||||
*
|
||||
* The commas in the string aim to increase ease of understanding
|
||||
* when read by a screenreader.
|
||||
*/
|
||||
var stringMap = {
|
||||
"(": "left parenthesis",
|
||||
")": "right parenthesis",
|
||||
"[": "open bracket",
|
||||
"]": "close bracket",
|
||||
"\\{": "left brace",
|
||||
"\\}": "right brace",
|
||||
"\\lvert": "open vertical bar",
|
||||
"\\rvert": "close vertical bar",
|
||||
"|": "vertical bar",
|
||||
"\\uparrow": "up arrow",
|
||||
"\\Uparrow": "up arrow",
|
||||
"\\downarrow": "down arrow",
|
||||
"\\Downarrow": "down arrow",
|
||||
"\\updownarrow": "up down arrow",
|
||||
"\\leftarrow": "left arrow",
|
||||
"\\Leftarrow": "left arrow",
|
||||
"\\rightarrow": "right arrow",
|
||||
"\\Rightarrow": "right arrow",
|
||||
"\\langle": "open angle",
|
||||
"\\rangle": "close angle",
|
||||
"\\lfloor": "open floor",
|
||||
"\\rfloor": "close floor",
|
||||
"\\int": "integral",
|
||||
"\\intop": "integral",
|
||||
"\\lim": "limit",
|
||||
"\\ln": "natural log",
|
||||
"\\log": "log",
|
||||
"\\sin": "sine",
|
||||
"\\cos": "cosine",
|
||||
"\\tan": "tangent",
|
||||
"\\cot": "cotangent",
|
||||
"\\sum": "sum",
|
||||
"/": "slash",
|
||||
",": "comma",
|
||||
".": "point",
|
||||
"-": "negative",
|
||||
"+": "plus",
|
||||
"~": "tilde",
|
||||
":": "colon",
|
||||
"?": "question mark",
|
||||
"'": "apostrophe",
|
||||
"\\%": "percent",
|
||||
" ": "space",
|
||||
"\\ ": "space",
|
||||
"\\$": "dollar sign",
|
||||
"\\angle": "angle",
|
||||
"\\degree": "degree",
|
||||
"\\circ": "circle",
|
||||
"\\vec": "vector",
|
||||
"\\triangle": "triangle",
|
||||
"\\pi": "pi",
|
||||
"\\prime": "prime",
|
||||
"\\infty": "infinity",
|
||||
"\\alpha": "alpha",
|
||||
"\\beta": "beta",
|
||||
"\\gamma": "gamma",
|
||||
"\\omega": "omega",
|
||||
"\\theta": "theta",
|
||||
"\\sigma": "sigma",
|
||||
"\\lambda": "lambda",
|
||||
"\\tau": "tau",
|
||||
"\\Delta": "delta",
|
||||
"\\delta": "delta",
|
||||
"\\mu": "mu",
|
||||
"\\rho": "rho",
|
||||
"\\nabla": "del",
|
||||
"\\ell": "ell",
|
||||
"\\ldots": "dots",
|
||||
// TODO: add entries for all accents
|
||||
"\\hat": "hat",
|
||||
"\\acute": "acute"
|
||||
};
|
||||
var powerMap = {
|
||||
"prime": "prime",
|
||||
"degree": "degrees",
|
||||
"circle": "degrees",
|
||||
"2": "squared",
|
||||
"3": "cubed"
|
||||
};
|
||||
var openMap = {
|
||||
"|": "open vertical bar",
|
||||
".": ""
|
||||
};
|
||||
var closeMap = {
|
||||
"|": "close vertical bar",
|
||||
".": ""
|
||||
};
|
||||
var binMap = {
|
||||
"+": "plus",
|
||||
"-": "minus",
|
||||
"\\pm": "plus minus",
|
||||
"\\cdot": "dot",
|
||||
"*": "times",
|
||||
"/": "divided by",
|
||||
"\\times": "times",
|
||||
"\\div": "divided by",
|
||||
"\\circ": "circle",
|
||||
"\\bullet": "bullet"
|
||||
};
|
||||
var relMap = {
|
||||
"=": "equals",
|
||||
"\\approx": "approximately equals",
|
||||
"≠": "does not equal",
|
||||
"\\geq": "is greater than or equal to",
|
||||
"\\ge": "is greater than or equal to",
|
||||
"\\leq": "is less than or equal to",
|
||||
"\\le": "is less than or equal to",
|
||||
">": "is greater than",
|
||||
"<": "is less than",
|
||||
"\\leftarrow": "left arrow",
|
||||
"\\Leftarrow": "left arrow",
|
||||
"\\rightarrow": "right arrow",
|
||||
"\\Rightarrow": "right arrow",
|
||||
":": "colon"
|
||||
};
|
||||
var accentUnderMap = {
|
||||
"\\underleftarrow": "left arrow",
|
||||
"\\underrightarrow": "right arrow",
|
||||
"\\underleftrightarrow": "left-right arrow",
|
||||
"\\undergroup": "group",
|
||||
"\\underlinesegment": "line segment",
|
||||
"\\utilde": "tilde"
|
||||
};
|
||||
|
||||
var buildString = (str, type, a11yStrings) => {
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
|
||||
var ret;
|
||||
|
||||
if (type === "open") {
|
||||
ret = str in openMap ? openMap[str] : stringMap[str] || str;
|
||||
} else if (type === "close") {
|
||||
ret = str in closeMap ? closeMap[str] : stringMap[str] || str;
|
||||
} else if (type === "bin") {
|
||||
ret = binMap[str] || str;
|
||||
} else if (type === "rel") {
|
||||
ret = relMap[str] || str;
|
||||
} else {
|
||||
ret = stringMap[str] || str;
|
||||
} // If the text to add is a number and there is already a string
|
||||
// in the list and the last string is a number then we should
|
||||
// combine them into a single number
|
||||
|
||||
|
||||
if (/^\d+$/.test(ret) && a11yStrings.length > 0 && // TODO(kevinb): check that the last item in a11yStrings is a string
|
||||
// I think we might be able to drop the nested arrays, which would make
|
||||
// this easier to type
|
||||
// $FlowFixMe
|
||||
/^\d+$/.test(a11yStrings[a11yStrings.length - 1])) {
|
||||
a11yStrings[a11yStrings.length - 1] += ret;
|
||||
} else if (ret) {
|
||||
a11yStrings.push(ret);
|
||||
}
|
||||
};
|
||||
|
||||
var buildRegion = (a11yStrings, callback) => {
|
||||
var regionStrings = [];
|
||||
a11yStrings.push(regionStrings);
|
||||
callback(regionStrings);
|
||||
};
|
||||
|
||||
var handleObject = (tree, a11yStrings, atomType) => {
|
||||
// Everything else is assumed to be an object...
|
||||
switch (tree.type) {
|
||||
case "accent":
|
||||
{
|
||||
buildRegion(a11yStrings, a11yStrings => {
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
a11yStrings.push("with");
|
||||
buildString(tree.label, "normal", a11yStrings);
|
||||
a11yStrings.push("on top");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "accentUnder":
|
||||
{
|
||||
buildRegion(a11yStrings, a11yStrings => {
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
a11yStrings.push("with");
|
||||
buildString(accentUnderMap[tree.label], "normal", a11yStrings);
|
||||
a11yStrings.push("underneath");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "accent-token":
|
||||
{
|
||||
// Used internally by accent symbols.
|
||||
break;
|
||||
}
|
||||
|
||||
case "atom":
|
||||
{
|
||||
var {
|
||||
text
|
||||
} = tree;
|
||||
|
||||
switch (tree.family) {
|
||||
case "bin":
|
||||
{
|
||||
buildString(text, "bin", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "close":
|
||||
{
|
||||
buildString(text, "close", a11yStrings);
|
||||
break;
|
||||
}
|
||||
// TODO(kevinb): figure out what should be done for inner
|
||||
|
||||
case "inner":
|
||||
{
|
||||
buildString(tree.text, "inner", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "open":
|
||||
{
|
||||
buildString(text, "open", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "punct":
|
||||
{
|
||||
buildString(text, "punct", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "rel":
|
||||
{
|
||||
buildString(text, "rel", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
tree.family;
|
||||
throw new Error("\"" + tree.family + "\" is not a valid atom type");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "color":
|
||||
{
|
||||
var color = tree.color.replace(/katex-/, "");
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
regionStrings.push("start color " + color);
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end color " + color);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "color-token":
|
||||
{
|
||||
// Used by \color, \colorbox, and \fcolorbox but not directly rendered.
|
||||
// It's a leaf node and has no children so just break.
|
||||
break;
|
||||
}
|
||||
|
||||
case "delimsizing":
|
||||
{
|
||||
if (tree.delim && tree.delim !== ".") {
|
||||
buildString(tree.delim, "normal", a11yStrings);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "genfrac":
|
||||
{
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
// genfrac can have unbalanced delimiters
|
||||
var {
|
||||
leftDelim,
|
||||
rightDelim
|
||||
} = tree; // NOTE: Not sure if this is a safe assumption
|
||||
// hasBarLine true -> fraction, false -> binomial
|
||||
|
||||
if (tree.hasBarLine) {
|
||||
regionStrings.push("start fraction");
|
||||
leftDelim && buildString(leftDelim, "open", regionStrings);
|
||||
buildA11yStrings(tree.numer, regionStrings, atomType);
|
||||
regionStrings.push("divided by");
|
||||
buildA11yStrings(tree.denom, regionStrings, atomType);
|
||||
rightDelim && buildString(rightDelim, "close", regionStrings);
|
||||
regionStrings.push("end fraction");
|
||||
} else {
|
||||
regionStrings.push("start binomial");
|
||||
leftDelim && buildString(leftDelim, "open", regionStrings);
|
||||
buildA11yStrings(tree.numer, regionStrings, atomType);
|
||||
regionStrings.push("over");
|
||||
buildA11yStrings(tree.denom, regionStrings, atomType);
|
||||
rightDelim && buildString(rightDelim, "close", regionStrings);
|
||||
regionStrings.push("end binomial");
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "hbox":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "kern":
|
||||
{
|
||||
// No op: we don't attempt to present kerning information
|
||||
// to the screen reader.
|
||||
break;
|
||||
}
|
||||
|
||||
case "leftright":
|
||||
{
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
buildString(tree.left, "open", regionStrings);
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
buildString(tree.right, "close", regionStrings);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "leftright-right":
|
||||
{
|
||||
// TODO: double check that this is a no-op
|
||||
break;
|
||||
}
|
||||
|
||||
case "lap":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mathord":
|
||||
{
|
||||
buildString(tree.text, "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "op":
|
||||
{
|
||||
var {
|
||||
body,
|
||||
name
|
||||
} = tree;
|
||||
|
||||
if (body) {
|
||||
buildA11yStrings(body, a11yStrings, atomType);
|
||||
} else if (name) {
|
||||
buildString(name, "normal", a11yStrings);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "op-token":
|
||||
{
|
||||
// Used internally by operator symbols.
|
||||
buildString(tree.text, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "ordgroup":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "overline":
|
||||
{
|
||||
buildRegion(a11yStrings, function (a11yStrings) {
|
||||
a11yStrings.push("start overline");
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
a11yStrings.push("end overline");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "phantom":
|
||||
{
|
||||
a11yStrings.push("empty space");
|
||||
break;
|
||||
}
|
||||
|
||||
case "raisebox":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "rule":
|
||||
{
|
||||
a11yStrings.push("rectangle");
|
||||
break;
|
||||
}
|
||||
|
||||
case "sizing":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "spacing":
|
||||
{
|
||||
a11yStrings.push("space");
|
||||
break;
|
||||
}
|
||||
|
||||
case "styling":
|
||||
{
|
||||
// We ignore the styling and just pass through the contents
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "sqrt":
|
||||
{
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
var {
|
||||
body,
|
||||
index
|
||||
} = tree;
|
||||
|
||||
if (index) {
|
||||
var indexString = flatten(buildA11yStrings(index, [], atomType)).join(",");
|
||||
|
||||
if (indexString === "3") {
|
||||
regionStrings.push("cube root of");
|
||||
buildA11yStrings(body, regionStrings, atomType);
|
||||
regionStrings.push("end cube root");
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("root");
|
||||
regionStrings.push("start index");
|
||||
buildA11yStrings(index, regionStrings, atomType);
|
||||
regionStrings.push("end index");
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("square root of");
|
||||
buildA11yStrings(body, regionStrings, atomType);
|
||||
regionStrings.push("end square root");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "supsub":
|
||||
{
|
||||
var {
|
||||
base,
|
||||
sub,
|
||||
sup
|
||||
} = tree;
|
||||
var isLog = false;
|
||||
|
||||
if (base) {
|
||||
buildA11yStrings(base, a11yStrings, atomType);
|
||||
isLog = base.type === "op" && base.name === "\\log";
|
||||
}
|
||||
|
||||
if (sub) {
|
||||
var regionName = isLog ? "base" : "subscript";
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start " + regionName);
|
||||
buildA11yStrings(sub, regionStrings, atomType);
|
||||
regionStrings.push("end " + regionName);
|
||||
});
|
||||
}
|
||||
|
||||
if (sup) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
var supString = flatten(buildA11yStrings(sup, [], atomType)).join(",");
|
||||
|
||||
if (supString in powerMap) {
|
||||
regionStrings.push(powerMap[supString]);
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("start superscript");
|
||||
buildA11yStrings(sup, regionStrings, atomType);
|
||||
regionStrings.push("end superscript");
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "text":
|
||||
{
|
||||
// TODO: handle other fonts
|
||||
if (tree.font === "\\textbf") {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start bold text");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end bold text");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start text");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end text");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "textord":
|
||||
{
|
||||
buildString(tree.text, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "smash":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "enclose":
|
||||
{
|
||||
// TODO: create a map for these.
|
||||
// TODO: differentiate between a body with a single atom, e.g.
|
||||
// "cancel a" instead of "start cancel, a, end cancel"
|
||||
if (/cancel/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start cancel");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end cancel");
|
||||
});
|
||||
break;
|
||||
} else if (/box/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start box");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end box");
|
||||
});
|
||||
break;
|
||||
} else if (/sout/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start strikeout");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end strikeout");
|
||||
});
|
||||
break;
|
||||
} else if (/phase/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start phase angle");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end phase angle");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
throw new Error("KaTeX-a11y: enclose node with " + tree.label + " not supported yet");
|
||||
}
|
||||
|
||||
case "vcenter":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "vphantom":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: vphantom not implemented yet");
|
||||
}
|
||||
|
||||
case "hphantom":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: hphantom not implemented yet");
|
||||
}
|
||||
|
||||
case "operatorname":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "array":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: array not implemented yet");
|
||||
}
|
||||
|
||||
case "raw":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: raw not implemented yet");
|
||||
}
|
||||
|
||||
case "size":
|
||||
{
|
||||
// Although there are nodes of type "size" in the parse tree, they have
|
||||
// no semantic meaning and should be ignored.
|
||||
break;
|
||||
}
|
||||
|
||||
case "url":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: url not implemented yet");
|
||||
}
|
||||
|
||||
case "tag":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: tag not implemented yet");
|
||||
}
|
||||
|
||||
case "verb":
|
||||
{
|
||||
buildString("start verbatim", "normal", a11yStrings);
|
||||
buildString(tree.body, "normal", a11yStrings);
|
||||
buildString("end verbatim", "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "environment":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: environment not implemented yet");
|
||||
}
|
||||
|
||||
case "horizBrace":
|
||||
{
|
||||
buildString("start " + tree.label.slice(1), "normal", a11yStrings);
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
buildString("end " + tree.label.slice(1), "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "infix":
|
||||
{
|
||||
// All infix nodes are replace with other nodes.
|
||||
break;
|
||||
}
|
||||
|
||||
case "includegraphics":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: includegraphics not implemented yet");
|
||||
}
|
||||
|
||||
case "font":
|
||||
{
|
||||
// TODO: callout the start/end of specific fonts
|
||||
// TODO: map \BBb{N} to "the naturals" or something like that
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "href":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: href not implemented yet");
|
||||
}
|
||||
|
||||
case "cr":
|
||||
{
|
||||
// This is used by environments.
|
||||
throw new Error("KaTeX-a11y: cr not implemented yet");
|
||||
}
|
||||
|
||||
case "underline":
|
||||
{
|
||||
buildRegion(a11yStrings, function (a11yStrings) {
|
||||
a11yStrings.push("start underline");
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
a11yStrings.push("end underline");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "xArrow":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: xArrow not implemented yet");
|
||||
}
|
||||
|
||||
case "cdlabel":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: cdlabel not implemented yet");
|
||||
}
|
||||
|
||||
case "cdlabelparent":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");
|
||||
}
|
||||
|
||||
case "mclass":
|
||||
{
|
||||
// \neq and \ne are macros so we let "htmlmathml" render the mathmal
|
||||
// side of things and extract the text from that.
|
||||
var _atomType = tree.mclass.slice(1); // $FlowFixMe: drop the leading "m" from the values in mclass
|
||||
|
||||
|
||||
buildA11yStrings(tree.body, a11yStrings, _atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mathchoice":
|
||||
{
|
||||
// TODO: track which which style we're using, e.g. dispaly, text, etc.
|
||||
// default to text style if even that may not be the correct style
|
||||
buildA11yStrings(tree.text, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "htmlmathml":
|
||||
{
|
||||
buildA11yStrings(tree.mathml, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "middle":
|
||||
{
|
||||
buildString(tree.delim, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "internal":
|
||||
{
|
||||
// internal nodes are never included in the parse tree
|
||||
break;
|
||||
}
|
||||
|
||||
case "html":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
tree.type;
|
||||
throw new Error("KaTeX a11y un-recognized type: " + tree.type);
|
||||
}
|
||||
};
|
||||
|
||||
var buildA11yStrings = function buildA11yStrings(tree, a11yStrings, atomType) {
|
||||
if (a11yStrings === void 0) {
|
||||
a11yStrings = [];
|
||||
}
|
||||
|
||||
if (tree instanceof Array) {
|
||||
for (var i = 0; i < tree.length; i++) {
|
||||
buildA11yStrings(tree[i], a11yStrings, atomType);
|
||||
}
|
||||
} else {
|
||||
handleObject(tree, a11yStrings, atomType);
|
||||
}
|
||||
|
||||
return a11yStrings;
|
||||
};
|
||||
|
||||
var flatten = function flatten(array) {
|
||||
var result = [];
|
||||
array.forEach(function (item) {
|
||||
if (item instanceof Array) {
|
||||
result = result.concat(flatten(item));
|
||||
} else {
|
||||
result.push(item);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
var renderA11yString = function renderA11yString(text, settings) {
|
||||
var tree = katex.__parse(text, settings);
|
||||
|
||||
var a11yStrings = buildA11yStrings(tree, [], "normal");
|
||||
return flatten(a11yStrings).join(", ");
|
||||
};
|
||||
|
||||
export default renderA11yString;
|
BIN
static/katex/fonts/KaTeX_AMS-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_AMS-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_AMS-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_AMS-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_AMS-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_AMS-Regular.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Caligraphic-Bold.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Caligraphic-Bold.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Caligraphic-Bold.woff
Normal file
BIN
static/katex/fonts/KaTeX_Caligraphic-Bold.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Caligraphic-Bold.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Caligraphic-Bold.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Caligraphic-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Caligraphic-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Caligraphic-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_Caligraphic-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Caligraphic-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Caligraphic-Regular.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Fraktur-Bold.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Fraktur-Bold.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Fraktur-Bold.woff
Normal file
BIN
static/katex/fonts/KaTeX_Fraktur-Bold.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Fraktur-Bold.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Fraktur-Bold.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Fraktur-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Fraktur-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Fraktur-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_Fraktur-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Fraktur-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Fraktur-Regular.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-Bold.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Main-Bold.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-Bold.woff
Normal file
BIN
static/katex/fonts/KaTeX_Main-Bold.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-Bold.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Main-Bold.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-BoldItalic.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Main-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-BoldItalic.woff
Normal file
BIN
static/katex/fonts/KaTeX_Main-BoldItalic.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-BoldItalic.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Main-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-Italic.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Main-Italic.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-Italic.woff
Normal file
BIN
static/katex/fonts/KaTeX_Main-Italic.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-Italic.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Main-Italic.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Main-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_Main-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Main-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Main-Regular.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Math-BoldItalic.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Math-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Math-BoldItalic.woff
Normal file
BIN
static/katex/fonts/KaTeX_Math-BoldItalic.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Math-BoldItalic.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Math-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Math-Italic.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Math-Italic.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Math-Italic.woff
Normal file
BIN
static/katex/fonts/KaTeX_Math-Italic.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Math-Italic.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Math-Italic.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_SansSerif-Bold.ttf
Normal file
BIN
static/katex/fonts/KaTeX_SansSerif-Bold.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_SansSerif-Bold.woff
Normal file
BIN
static/katex/fonts/KaTeX_SansSerif-Bold.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_SansSerif-Bold.woff2
Normal file
BIN
static/katex/fonts/KaTeX_SansSerif-Bold.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_SansSerif-Italic.ttf
Normal file
BIN
static/katex/fonts/KaTeX_SansSerif-Italic.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_SansSerif-Italic.woff
Normal file
BIN
static/katex/fonts/KaTeX_SansSerif-Italic.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_SansSerif-Italic.woff2
Normal file
BIN
static/katex/fonts/KaTeX_SansSerif-Italic.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_SansSerif-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_SansSerif-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_SansSerif-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_SansSerif-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_SansSerif-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_SansSerif-Regular.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Script-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Script-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Script-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_Script-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Script-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Script-Regular.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size1-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Size1-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size1-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_Size1-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size1-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Size1-Regular.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size2-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Size2-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size2-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_Size2-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size2-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Size2-Regular.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size3-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Size3-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size3-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_Size3-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size3-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Size3-Regular.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size4-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Size4-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size4-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_Size4-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Size4-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Size4-Regular.woff2
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Typewriter-Regular.ttf
Normal file
BIN
static/katex/fonts/KaTeX_Typewriter-Regular.ttf
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Typewriter-Regular.woff
Normal file
BIN
static/katex/fonts/KaTeX_Typewriter-Regular.woff
Normal file
Binary file not shown.
BIN
static/katex/fonts/KaTeX_Typewriter-Regular.woff2
Normal file
BIN
static/katex/fonts/KaTeX_Typewriter-Regular.woff2
Normal file
Binary file not shown.
1079
static/katex/katex.css
Normal file
1079
static/katex/katex.css
Normal file
File diff suppressed because it is too large
Load Diff
18050
static/katex/katex.js
Normal file
18050
static/katex/katex.js
Normal file
File diff suppressed because it is too large
Load Diff
1
static/katex/katex.min.css
vendored
Normal file
1
static/katex/katex.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/katex/katex.min.js
vendored
Normal file
1
static/katex/katex.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
17679
static/katex/katex.mjs
Normal file
17679
static/katex/katex.mjs
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user