diff --git a/web/package.json b/web/package.json index 15095e0d3..b24163bb7 100644 --- a/web/package.json +++ b/web/package.json @@ -21,6 +21,7 @@ "class-variance-authority": "^0.7.0", "framer-motion": "^10.16.4", "highlight.js": "^11.9.0", + "postcss-url": "10.1.3", "jotai": "^2.6.0", "katex": "^0.16.10", "lodash": "^4.17.21", diff --git a/web/postcss.config.js b/web/postcss.config.js index 33ad091d2..fa30f9c8c 100644 --- a/web/postcss.config.js +++ b/web/postcss.config.js @@ -1,6 +1,10 @@ module.exports = { plugins: { - tailwindcss: {}, - autoprefixer: {}, + // eslint-disable-next-line @typescript-eslint/naming-convention + 'postcss-url': { + url: 'inline', + }, + 'tailwindcss': {}, + 'autoprefixer': {}, }, } diff --git a/web/styles/main.scss b/web/styles/main.scss index 3259f6c34..8e952af5c 100644 --- a/web/styles/main.scss +++ b/web/styles/main.scss @@ -1,14 +1,14 @@ // Tailwind - @import 'tailwindcss/base'; @import 'tailwindcss/components'; @import 'tailwindcss/utilities'; @import '@janhq/joi/dist/main.css'; -@import 'katex/dist/katex.min.css'; @import './base/global.scss'; +@import './vendor/katex.scss'; + @import './components/loader.scss'; @import './components/code-block.scss'; @import './components/message.scss'; diff --git a/web/styles/vendor/katex-fonts.scss b/web/styles/vendor/katex-fonts.scss new file mode 100644 index 000000000..a1b3499bc --- /dev/null +++ b/web/styles/vendor/katex-fonts.scss @@ -0,0 +1,71 @@ +$font-folder: 'katex-fonts' !default; +$use-woff2: true !default; +$use-woff: true !default; +$use-ttf: true !default; + +@function generate-src($family, $family-suffix) { + $src: null; + @if $use-woff2 { + $src: append( + $src, + url('#{$font-folder}/KaTeX_#{$family}-#{$family-suffix}.woff2') + format('woff2'), + comma + ); + } + + @return $src; +} + +@function generate-suffix($weight, $style) { + $suffix: null; + + @if $weight == normal and $style == normal { + $suffix: 'Regular'; + } + @if $weight == normal and $style == italic { + $suffix: 'Italic'; + } + @if $weight == bold and $style == normal { + $suffix: 'Bold'; + } + @if $weight == bold and $style == italic { + $suffix: 'BoldItalic'; + } + + @return $suffix; +} + +@mixin font-face($family, $weight, $style) { + $suffix: generate-suffix($weight, $style); + $src: generate-src($family, $suffix); + + @font-face { + font-family: 'KaTeX_#{$family}'; + src: $src; + font-weight: $weight; + font-style: $style; + font-display: swap; + } +} + +@include font-face('AMS', normal, normal); +@include font-face('Caligraphic', bold, normal); +@include font-face('Caligraphic', normal, normal); +@include font-face('Fraktur', bold, normal); +@include font-face('Fraktur', normal, normal); +@include font-face('Main', bold, normal); +@include font-face('Main', bold, italic); +@include font-face('Main', normal, italic); +@include font-face('Main', normal, normal); +@include font-face('Math', bold, italic); +@include font-face('Math', normal, italic); +@include font-face('SansSerif', bold, normal); +@include font-face('SansSerif', normal, italic); +@include font-face('SansSerif', normal, normal); +@include font-face('Script', normal, normal); +@include font-face('Size1', normal, normal); +@include font-face('Size2', normal, normal); +@include font-face('Size3', normal, normal); +@include font-face('Size4', normal, normal); +@include font-face('Typewriter', normal, normal); diff --git a/web/styles/vendor/katex-fonts/KaTeX_AMS-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_AMS-Regular.woff2 new file mode 100644 index 000000000..0acaaff03 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_AMS-Regular.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Caligraphic-Bold.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Caligraphic-Bold.woff2 new file mode 100644 index 000000000..f390922ec Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Caligraphic-Bold.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Caligraphic-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Caligraphic-Regular.woff2 new file mode 100644 index 000000000..75344a1f9 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Caligraphic-Regular.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Fraktur-Bold.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Fraktur-Bold.woff2 new file mode 100644 index 000000000..395f28bea Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Fraktur-Bold.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Fraktur-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Fraktur-Regular.woff2 new file mode 100644 index 000000000..735f6948d Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Fraktur-Regular.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Main-Bold.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Main-Bold.woff2 new file mode 100644 index 000000000..ab2ad21da Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Main-Bold.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Main-BoldItalic.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Main-BoldItalic.woff2 new file mode 100644 index 000000000..5931794de Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Main-BoldItalic.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Main-Italic.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Main-Italic.woff2 new file mode 100644 index 000000000..b50920e13 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Main-Italic.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Main-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Main-Regular.woff2 new file mode 100644 index 000000000..eb24a7ba2 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Main-Regular.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Math-BoldItalic.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Math-BoldItalic.woff2 new file mode 100644 index 000000000..29657023a Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Math-BoldItalic.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Math-Italic.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Math-Italic.woff2 new file mode 100644 index 000000000..215c143fd Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Math-Italic.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_SansSerif-Bold.woff2 b/web/styles/vendor/katex-fonts/KaTeX_SansSerif-Bold.woff2 new file mode 100644 index 000000000..cfaa3bda5 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_SansSerif-Bold.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_SansSerif-Italic.woff2 b/web/styles/vendor/katex-fonts/KaTeX_SansSerif-Italic.woff2 new file mode 100644 index 000000000..349c06dc6 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_SansSerif-Italic.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_SansSerif-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_SansSerif-Regular.woff2 new file mode 100644 index 000000000..a90eea85f Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_SansSerif-Regular.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Script-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Script-Regular.woff2 new file mode 100644 index 000000000..b3048fc11 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Script-Regular.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Size1-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Size1-Regular.woff2 new file mode 100644 index 000000000..c5a8462fb Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Size1-Regular.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Size2-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Size2-Regular.woff2 new file mode 100644 index 000000000..e1bccfe24 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Size2-Regular.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Size3-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Size3-Regular.woff2 new file mode 100644 index 000000000..249a28662 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Size3-Regular.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Size4-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Size4-Regular.woff2 new file mode 100644 index 000000000..680c13085 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Size4-Regular.woff2 differ diff --git a/web/styles/vendor/katex-fonts/KaTeX_Typewriter-Regular.woff2 b/web/styles/vendor/katex-fonts/KaTeX_Typewriter-Regular.woff2 new file mode 100644 index 000000000..771f1af70 Binary files /dev/null and b/web/styles/vendor/katex-fonts/KaTeX_Typewriter-Regular.woff2 differ diff --git a/web/styles/vendor/katex.scss b/web/styles/vendor/katex.scss new file mode 100644 index 000000000..3d7b06688 --- /dev/null +++ b/web/styles/vendor/katex.scss @@ -0,0 +1,671 @@ +/* stylelint-disable font-family-no-missing-generic-family-keyword */ +@import './katex-fonts.scss'; + +// The mu unit is defined as 1/18 em +$mu: calc(1em / 18); + +// The version is dynamically set from package.json via webpack.common.js +$version: '' !default; + +.katex { + font: + normal 1.21em KaTeX_Main, + Times New Roman, + serif; + line-height: 1.2; + + // Protect elements inside .katex from inheriting text-indent. + text-indent: 0; + + // Prevent a rendering bug that misplaces \vec in Chrome. + text-rendering: auto; + + * { + // Prevent background resetting on elements in Windows's high-contrast + // mode, while still allowing background/foreground setting on root .katex + -ms-high-contrast-adjust: none !important; + + // Insulate fraction bars and rules from CSS that sets border-color. + border-color: currentColor; + } + + .katex-version::after { + content: $version; + } + + .katex-mathml { + /* Accessibility hack to only show to screen readers + Found at: http://a11yproject.com/posts/how-to-hide-content/ */ + position: absolute; + clip: rect(1px, 1px, 1px, 1px); + padding: 0; + border: 0; + height: 1px; + width: 1px; + overflow: hidden; + } + + .katex-html { + /* \newline is an empty block at top level, between .base elements */ + > .newline { + display: block; + } + } + + .base { + position: relative; + display: inline-block; + white-space: nowrap; + + // Fix width of containers of negative spaces, working around Chrome bug. + width: min-content; + } + + .strut { + display: inline-block; + } + + // Text font weights + .textbf { + font-weight: bold; + } + + // Text font shapes. + .textit { + font-style: italic; + } + + // Text font families. + .textrm { + font-family: KaTeX_Main; + } + + .textsf { + font-family: KaTeX_SansSerif; + } + + .texttt { + font-family: KaTeX_Typewriter; + } + + // Math fonts. + .mathnormal { + font-family: KaTeX_Math; + font-style: italic; + } + + .mathit { + font-family: KaTeX_Main; + font-style: italic; + } + + .mathrm { + font-style: normal; + } + + .mathbf { + font-family: KaTeX_Main; + font-weight: bold; + } + + .boldsymbol { + font-family: KaTeX_Math; + font-weight: bold; + font-style: italic; + } + + .amsrm { + font-family: KaTeX_AMS; + } + + .mathbb, + .textbb { + font-family: KaTeX_AMS; + } + + .mathcal { + font-family: KaTeX_Caligraphic; + } + + .mathfrak, + .textfrak { + font-family: KaTeX_Fraktur; + } + + .mathboldfrak, + .textboldfrak { + font-family: KaTeX_Fraktur; + font-weight: bold; + } + + .mathtt { + font-family: KaTeX_Typewriter; + } + + .mathscr, + .textscr { + font-family: KaTeX_Script; + } + + .mathsf, + .textsf { + font-family: KaTeX_SansSerif; + } + + .mathboldsf, + .textboldsf { + font-family: KaTeX_SansSerif; + font-weight: bold; + } + + .mathitsf, + .textitsf { + font-family: KaTeX_SansSerif; + font-style: italic; + } + + .mainrm { + font-family: KaTeX_Main; + font-style: normal; + } + + // This value is also used in fontMetrics.js, if you change it make sure the + // values match. + $ptperem: 10; + $nulldelimiterspace: calc(1.2em / $ptperem); + + $muspace: 0.055556em; // 1mu + $thinspace: 0.16667em; // 3mu + $mediumspace: 0.22222em; // 4mu + $thickspace: 0.27778em; // 5mu + + .vlist-t { + display: inline-table; + table-layout: fixed; + border-collapse: collapse; + } + + .vlist-r { + display: table-row; + } + + .vlist { + display: table-cell; + vertical-align: bottom; + position: relative; + + > span { + display: block; + height: 0; + position: relative; + + > span { + display: inline-block; + } + + > .pstrut { + overflow: hidden; + width: 0; + } + } + } + + .vlist-t2 { + margin-right: -2px; + } + + .vlist-s { + // This cell solves Safari rendering problems. It has text content, so + // its baseline is used for the table. A very small font avoids line-box + // issues; absolute units prevent user font-size overrides from breaking + // rendering. Safari refuses to make the box zero-width, so we give it + // a known width and compensate with negative right margin on the + // inline-table. To prevent the "width: min-content" Chrome workaround + // from shrinking this box, we also set min-width. + display: table-cell; + vertical-align: bottom; + font-size: 1px; + width: 2px; + min-width: 2px; + } + + .vbox { + display: inline-flex; + flex-direction: column; + align-items: baseline; + } + + .hbox { + display: inline-flex; + flex-direction: row; + width: 100%; + } + + .thinbox { + display: inline-flex; + flex-direction: row; + width: 0; + max-width: 0; // necessary for Safari + } + + .msupsub { + text-align: left; + } + + .mfrac { + > span > span { + text-align: center; + } + + .frac-line { + display: inline-block; + width: 100%; + border-bottom-style: solid; + } + } + + // Prevent Chrome from disappearing frac-lines, rules, etc. + .mfrac .frac-line, + .overline .overline-line, + .underline .underline-line, + .hline, + .hdashline, + .rule { + min-height: 1px; + } + + .mspace { + display: inline-block; + } + + .llap, + .rlap, + .clap { + width: 0; + position: relative; + + > .inner { + position: absolute; + } + + > .fix { + display: inline-block; + } + } + + .llap > .inner { + right: 0; + } + + .rlap > .inner, + .clap > .inner { + left: 0; + } + + .clap > .inner > span { + margin-left: -50%; + margin-right: 50%; + } + + .rule { + display: inline-block; + border: solid 0; + position: relative; + } + + .overline .overline-line, + .underline .underline-line, + .hline { + display: inline-block; + width: 100%; + border-bottom-style: solid; + } + + .hdashline { + display: inline-block; + width: 100%; + border-bottom-style: dashed; + } + + .sqrt { + > .root { + /* These values are taken from the definition of `\r@@t`, + `\mkern 5mu` and `\mkern -10mu`. */ + margin-left: calc(5 * $mu); + margin-right: calc(-10 * $mu); + } + } + + .sizing, + .fontsize-ensurer { + $sizes: 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.44, 1.728, 2.074, 2.488; + + @for $from from 1 through length($sizes) { + @for $to from 1 through length($sizes) { + &.reset-size#{$from}.size#{$to} { + /* stylelint-disable-next-line */ + font-size: calc((nth($sizes, $to) / nth($sizes, $from)) * 1em); + } + } + } + } + + .delimsizing { + &.size1 { + font-family: KaTeX_Size1; + } + &.size2 { + font-family: KaTeX_Size2; + } + &.size3 { + font-family: KaTeX_Size3; + } + &.size4 { + font-family: KaTeX_Size4; + } + + &.mult { + .delim-size1 > span { + font-family: KaTeX_Size1; + } + + .delim-size4 > span { + font-family: KaTeX_Size4; + } + } + } + + .nulldelimiter { + display: inline-block; + width: $nulldelimiterspace; + } + + .delimcenter { + position: relative; + } + + .op-symbol { + position: relative; + + &.small-op { + font-family: KaTeX_Size1; + } + + &.large-op { + font-family: KaTeX_Size2; + } + } + + .op-limits { + > .vlist-t { + text-align: center; + } + } + + .accent { + > .vlist-t { + text-align: center; + } + + .accent-body { + position: relative; // so that 'left' can shift the accent + } + + // Accents that are not of the accent-full class have zero width + // (do not contribute to the width of the final symbol). + .accent-body:not(.accent-full) { + width: 0; + } + } + + .overlay { + display: block; + } + + .mtable { + .vertical-separator { + display: inline-block; + // margin and border-right are set in JavaScript + min-width: 1px; // Prevent Chrome from omitting a line. + } + + .arraycolsep { + display: inline-block; + } + + .col-align-c > .vlist-t { + text-align: center; + } + + .col-align-l > .vlist-t { + text-align: left; + } + + .col-align-r > .vlist-t { + text-align: right; + } + } + + .svg-align { + text-align: left; + } + + svg { + display: block; + position: absolute; // absolute relative to parent + width: 100%; + height: inherit; + + // We want to inherit colors from our environment + fill: currentColor; + stroke: currentColor; + + // But path elements should not have an outline by default + // that would make them bigger than we expect. + path { + stroke: none; + } + + // And we don't want to inherit any other style properties + // that could affect SVG rendering without affecting font + // rendering. So we reset these properties to their default + // values for every element. + // See https://www.w3.org/TR/SVG/painting.html + fill-rule: nonzero; + fill-opacity: 1; + stroke-width: 1; + stroke-linecap: butt; + stroke-linejoin: miter; + stroke-miterlimit: 4; + stroke-dasharray: none; + stroke-dashoffset: 0; + stroke-opacity: 1; + } + + img { + border-style: none; + min-width: 0; + min-height: 0; + max-width: none; + max-height: none; + } + + // Define CSS for image whose width will match its span width. + .stretchy { + width: 100%; + display: block; + position: relative; + overflow: hidden; + + &::before, + &::after { + content: ''; + } + } + + // Hide the long tail of a stretchy SVG. + .hide-tail { + width: 100%; // necessary only to get IE to work properly + position: relative; // ditto + overflow: hidden; // This line applies to all browsers. + } + + .halfarrow-left { + position: absolute; + left: 0; + width: 50.2%; + overflow: hidden; + } + + .halfarrow-right { + position: absolute; + right: 0; + width: 50.2%; + overflow: hidden; + } + + .brace-left { + position: absolute; + left: 0; + width: 25.1%; + overflow: hidden; + } + + .brace-center { + position: absolute; + left: 25%; + width: 50%; + overflow: hidden; + } + + .brace-right { + position: absolute; + right: 0; + width: 25.1%; + overflow: hidden; + } + + // Lengthen the extensible arrows via padding. + .x-arrow-pad { + padding: 0 0.5em; + } + + .cd-arrow-pad { + padding: 0 0.55556em 0 0.27778em; // \;{#1}\;\; + } + + .x-arrow, + .mover, + .munder { + text-align: center; + } + + .boxpad { + padding: 0 0.3em; // \fboxsep = 3pt + } + + .fbox, + .fcolorbox { + box-sizing: border-box; + border: 0.04em solid; // \fboxrule = 0.4pt + } + + .cancel-pad { + padding: 0 0.2em; // ref: cancel package \advance\dimen@ 2\p@ % "+2" + } + + .cancel-lap { + margin-left: -0.2em; // \cancel does not affect horizontal spacing. + margin-right: -0.2em; // Apply negative margin to correct for 0.2em padding + } // inside the \cancel group. + + .sout { + border-bottom-style: solid; + border-bottom-width: 0.08em; + } + + .angl { + // from package actuarialangle, which is always used in a subscript. + box-sizing: border-box; + border-top: 0.049em solid; // defaultRuleThickness in scriptstyle + border-right: 0.049em solid; // ditto + margin-right: 0.03889em; // 1 mu + } + + .anglpad { + padding: 0 0.03889em; // pad 1mu left and right (in scriptstyle) + } + + .eqn-num::before { + counter-increment: katexEqnNo; + content: '(' counter(katexEqnNo) ')'; + } + + .mml-eqn-num::before { + counter-increment: mmlEqnNo; + content: '(' counter(mmlEqnNo) ')'; + } + + .mtr-glue { + width: 50%; + } + + .cd-vert-arrow { + display: inline-block; + position: relative; + } + + .cd-label-left { + display: inline-block; + position: absolute; + right: calc(50% + 0.3em); + text-align: left; + } + + .cd-label-right { + display: inline-block; + position: absolute; + left: calc(50% + 0.3em); + text-align: right; + } +} + +.katex-display { + display: block; + margin: 1em 0; + text-align: center; + + > .katex { + display: block; + text-align: center; + white-space: nowrap; + + > .katex-html { + display: block; + position: relative; + + > .tag { + position: absolute; + right: 0; + } + } + } +} + +// Left-justified tags (default is right-justified) +.katex-display.leqno > .katex > .katex-html > .tag { + left: 0; + right: auto; +} + +// Flush-left display math +.katex-display.fleqn > .katex { + text-align: left; + padding-left: 2em; +} + +// Automatic equation numbers for some environments. +// Use parallel counters for HTML and MathML. +body { + counter-reset: katexEqnNo mmlEqnNo; +}