Toggle diff (289 lines)
diff --git a/gnu/packages/javascript.scm b/gnu/packages/javascript.scm
index ee7a48154c..76a51c22ac 100644
--- a/gnu/packages/javascript.scm
+++ b/gnu/packages/javascript.scm
@@ -32,6 +32,7 @@ (define-module (gnu packages javascript)
#:use-module (gnu packages compression)
#:use-module (gnu packages fontutils)
#:use-module (gnu packages java)
+ #:use-module (gnu packages man)
#:use-module (gnu packages node)
#:use-module (gnu packages perl)
#:use-module (gnu packages python)
@@ -382,7 +383,7 @@ (define-public js-mathjax-for-r-mathjaxr
(define-public font-katex
(package
(name "font-katex")
- (version "0.16.4")
+ (version "0.16.9")
(source
(origin
(method git-fetch)
@@ -391,7 +392,7 @@ (define-public font-katex
(commit (string-append "v" version))))
(sha256
(base32
- "0z6y2188lhfv0gk0hp4rm37g6fs99qb3ab2q3n9g76ga9dwxhw3s"))
+ "1aq8n9s4r15m1fdi4h58qxal4brkafm4xsw6rpz40wqi9454kkgn"))
(snippet
;; unbundle generated files
#~(begin
@@ -446,6 +447,256 @@ (define-public font-katex
(description "This package contains the fonts required for KaTeX.")
(license license:expat)))
+(define-public katex
+ (package
+ (inherit font-katex)
+ (name "katex")
+ (outputs '("out" "dist"))
+ (build-system node-build-system)
+ (native-inputs
+ (list esbuild
+ flow-remove-types
+ help2man
+ lessc))
+ (inputs
+ (list font-katex
+ js-commander))
+ (arguments
+ (list
+ #:tests? #f ; many more dependencies
+ #:modules
+ `((guix build node-build-system)
+ (ice-9 match)
+ (srfi srfi-1)
+ (srfi srfi-26)
+ (guix build utils))
+ #:phases
+ #~(modify-phases %standard-phases
+ (add-before 'patch-dependencies 'move-sources
+ (lambda* (#:key inputs #:allow-other-keys)
+ ;; Our node-build-system doesn't properly respect the "files"
+ ;; entry in "package.json" to determine which files to install.
+ ;; This case is particularly egregious because the source
+ ;; repository also contains the source for the whole katex.org
+ ;; website. For now, manually do what "files" ought to do.
+ (mkdir "../guix-source")
+ (copy-recursively "src" "../guix-source/src")
+ (copy-recursively "contrib" "../guix-source/contrib")
+ (for-each (cut install-file <> "../guix-source")
+ '("README.md"
+ "LICENSE"
+ "package.json"
+ "katex.js"
+ "cli.js"))
+ (install-file
+ (search-input-file inputs "share/katex/fontMetricsData.js")
+ "../guix-source/src")
+ (chdir "../guix-source")))
+ (add-after 'move-sources 'patch-package-json
+ (lambda args
+ (with-atomic-json-file-replacement "package.json"
+ (match-lambda
+ (('@ . alist)
+ (cons '@
+ (filter-map
+ (match-lambda
+ (((or "devDependencies" "scripts") . _)
+ #f)
+ ;; ESBuild can't generate Universal Module Definitions,
+ ;; so keep our CJS separate from our browser builds:
+ (("files" . lst)
+ `("files" "guix-node-cjs/" ,@lst))
+ (("main" . "dist/katex.js")
+ `("main" . "guix-node-cjs/katex.js"))
+ (("exports" '@ . alist)
+ `("exports" @
+ ,@(map (match-lambda
+ (("./*" . "./*")
+ `("./*" . "./*"))
+ ((lhs '@ . alist)
+ `(,lhs @
+ ,@(map (match-lambda
+ (("require" . ,str)
+ (cons
+ "require"
+ (string-append
+ "./guix-node-cjs/"
+ (substring str
+ (string-length
+ "./dist")))))
+ (other
+ other))
+ alist))))
+ alist)))
+ (other
+ other))
+ alist)))))))
+ (add-after 'patch-dependencies 'patch-sources
+ (lambda* (#:key inputs #:allow-other-keys)
+ (substitute* "src/SourceLocation.js"
+ ;; for some reason, the + prefix isn't handled
+ ;; by flow-remove-types
+ (("[+](lexer|start|end)" _ name)
+ name))
+ (substitute* "src/fonts.less"
+ ;; what webpack would do
+ (("@font-folder: \"\\.\\./fonts\";" orig)
+ (string-append "@font-folder: \"fonts\"; // " orig)))
+ (define version
+ #$(package-version this-package))
+ (substitute* "src/katex.less"
+ (("@version: \"\";" orig)
+ (string-append "@version: \"" version "\"; // " orig)))
+ (substitute* "katex.js"
+ (("version: __VERSION__," orig)
+ (string-append "version: \"" version "\", // " orig)))))
+ (add-after 'patch-sources 'erase-types
+ (lambda args
+ (invoke "flow-remove-types"
+ "--sourcemaps"
+ "--out-dir" "../erased/src/"
+ "src/")
+ (invoke "flow-remove-types"
+ "--sourcemaps"
+ "--out-dir" "../erased/"
+ "katex.js")
+ (invoke "flow-remove-types"
+ "--sourcemaps"
+ "--out-dir" "../erased/contrib/"
+ "contrib/")))
+ (add-after 'erase-types 'build-js
+ (lambda args
+ (with-directory-excursion "../erased"
+ ;; ^ avoid "../erased" in generated code
+ (define (esbuild . args)
+ (apply invoke `("esbuild"
+ "--bundle"
+ "--log-limit=0"
+ "--platform=neutral"
+ ,@args)))
+ (esbuild "--outfile=../guix-source/dist/katex.mjs"
+ "--format=esm"
+ "katex.js")
+ ;; Workaround for different handling of ES6 default export
+ ;; when generating CJS:
+ (esbuild "--outfile=katex-cjs.js"
+ "--format=cjs"
+ "katex.js")
+ (with-output-to-file "katex-wrapper.js"
+ (lambda ()
+ (display
+ "module.exports = require('./katex-cjs.js').default;\n")))
+ (esbuild "--outfile=../guix-source/guix-node-cjs/katex.js"
+ "--format=cjs"
+ "katex-wrapper.js")
+ (esbuild "--outfile=../guix-source/dist/katex.js"
+ "--format=iife"
+ "--global-name=katex"
+ "katex-wrapper.js")
+ (esbuild "--outfile=../guix-source/dist/katex.min.js"
+ "--minify"
+ "--format=iife"
+ "--global-name=katex"
+ "katex-wrapper.js")
+ ;; Build extensions:
+ (for-each
+ (match-lambda
+ ((name export)
+ ;; The copy-tex extension doesn't actually import katex,
+ ;; but it's harmless to handle it the same way.
+ (with-directory-excursion (string-append "contrib/" name)
+ (esbuild (string-append "--outfile=../../../guix-source"
+ "/guix-node-cjs/contrib/"
+ name ".js")
+ "--format=cjs"
+ "--external:katex"
+ (string-append name ".js"))
+ (substitute* (string-append name ".js")
+ (("import katex from \"katex\";")
+ "import katex from \"../katex.mjs\";"))
+ (esbuild (string-append "--outfile=" name ".mjs")
+ "--format=esm"
+ "--external:../katex.mjs"
+ (string-append name ".js"))
+ (install-file (string-append name ".mjs")
+ "../../../guix-source/dist/contrib")
+ (substitute* (string-append name ".js")
+ (("import katex")
+ "// import katex"))
+ (for-each
+ (lambda (minify?)
+ (apply
+ esbuild
+ `(,(string-append "--outfile=../../.."
+ "/guix-source/dist/contrib/"
+ name
+ (if minify? ".min" "")
+ ".js")
+ "--format=iife"
+ ,@(if minify?
+ '("--minify")
+ '())
+ ,@(if export
+ `("--global-name=guixTmp"
+ ,(string-append "--banner:js=const "
+ export
+ " = (() => {")
+ "--footer:js=return guixTmp.default;\n})();")
+ '())
+ ,(string-append name ".js"))))
+ '(#t #f)))))
+ '(("auto-render" "renderMathInElement")
+ ("copy-tex" #f)
+ ("mathtex-script-type" #f)
+ ("mhchem" #f)
+ ("render-a11y-string" "renderA11yString"))))))
+ (add-after 'build-js 'build-css
+ (lambda args
+ (invoke "lessc" "src/katex.less" "dist/katex.css")))
+ (add-after 'install 'generate-man-page
+ (lambda args
+ (invoke "help2man"
+ "-N"
+ "-n" "render TeX math to HTML and MathML"
+ "--output=katex.1"
+ (string-append #$output "/bin/katex"))
+ (install-file "katex.1"
+ (string-append #$output "/share/man/man1"))))
+ (add-after 'generate-man-page 'install-dist
+ (lambda* (#:key inputs #:allow-other-keys)
+ ;; The CSS, fonts, etc. needed for KaTeX, plus the optional
+ ;; bundled version of the JavaScript for dynamic use in the
+ ;; browser, are in the 'dist' directory of the Node module.
+ ;; Putting them in a separate output lets them be used without
+ ;; retaining a reference to Node and the cli utility.
+ ;; In Debian, 'dist' is a symlink to /usr/share/javascript/katex:
+ ;; do likewise to help tools that may need to find it.
+ (define up-dist-dir
+ (string-append #$output:dist "/share/javascript"))
+ (define dist-dir
+ (string-append up-dist-dir "/katex"))
+ (mkdir-p up-dist-dir)
+ (with-directory-excursion
+ (string-append #$output "/lib/node_modules/katex")
+ (rename-file "dist" dist-dir)
+ (symlink dist-dir "dist"))
+ (with-directory-excursion dist-dir
+ ;; Link the fonts to where the CSS expects them:
+ (symlink (search-input-directory inputs
+ "share/fonts/truetype/katex")
+ "fonts")
+ ;; We can't actually minify the CSS, but fake it for anything
+ ;; that may expect it. With Brotli compression, the difference
+ ;; is only about 300 bytes anyway.
+ (symlink "katex.css" "katex.min.css")))))))
+ (synopsis "Fast math typesetting for the web")
+ (description "KaTeX renders TeX math notation to HTML and/or MathML. The
+rendered output does not depend on JavaScript, so rendering can be done
+entirely ahead-of-time using the @command{katex} command-line tool. When
+desired, KaTeX can also be used as a JavaScript library in the browser to
+render math dynamically, and it is designed to be fast, even on pages with
+hundreds of mathematical expressions.")))
+
(define-public js-commander
(package
(name "js-commander")
--
2.41.0