From 3467cadd6e40658cc6c6349308eae6c2111cf8d7 Mon Sep 17 00:00:00 2001 From: Alexander Artemenko Date: Wed, 1 Sep 2021 21:26:05 +0300 Subject: [PATCH 01/11] Generate CSS using a current theme. --- src/builder.lisp | 169 ++++++++++++++++++---------------------- src/themes/api.lisp | 45 ++++++++++- src/themes/default.lisp | 5 +- 3 files changed, 122 insertions(+), 97 deletions(-) diff --git a/src/builder.lisp b/src/builder.lisp index 4466be37..7adbe305 100644 --- a/src/builder.lisp +++ b/src/builder.lisp @@ -259,100 +259,81 @@ (declare (ignore c)) (incf num-warnings)))) (40ants-doc/commondoc/format:with-format (format) - (let* ((theme (make-instance theme)) - (sections (uiop:ensure-list sections)) - (pages (mapcar #'40ants-doc/page:ensure-page sections)) - (page-documents (mapcar - #'40ants-doc/commondoc/builder:to-commondoc - pages)) - (full-document (process-document - (common-doc:make-document "Documentation" - :children page-documents) - :base-url base-url)) - (absolute-dir (uiop:ensure-absolute-pathname base-dir - (probe-file "."))) - (css-filename (uiop:merge-pathnames* #P"theme.css" absolute-dir)) - (40ants-doc/commondoc/toc::*full-document* full-document) - (output-paths nil)) - - (ensure-directories-exist absolute-dir) - - (flet ((make-full-filename (page) - ;; PAGE argument could be either PAGE object or string denoting a relative path - ;; of HTML page. - (let* ((page-base-dir (or (when (typep page '40ants-doc/commondoc/page:page) - (page-base-dir page)) - base-dir)) - (absolute-dir (uiop:ensure-absolute-pathname page-base-dir - (probe-file "."))) - (filename (etypecase page - (40ants-doc/commondoc/page:page - (40ants-doc/commondoc/page::full-filename page)) - (string - page)))) - (uiop:merge-pathnames* filename absolute-dir)))) - (loop with global-format = format - for document in page-documents - for full-filename = (make-full-filename document) - for format = (or - ;; Page may override global format setting - (page-format document) - global-format) - do (ensure-directories-exist full-filename) - (uiop:with-output-file (stream full-filename - :if-exists :supersede) - (common-doc.format:emit-document (make-instance format) - document - stream) - (push full-filename output-paths))) - - (when (eql format - 'common-html:html) - (uiop:with-output-file (stream css-filename - :if-exists :supersede) - (write-string (40ants-doc/themes/api:render-css theme) - stream) - (terpri stream)) - - (let* ((page (40ants-doc/commondoc/page:make-page nil "search/index" - :title "Search Page" - :format :html)) - (filename (make-full-filename page))) - (ensure-directories-exist filename) - (uiop:with-output-file (common-html.emitter::*output-stream* - filename - :if-exists :supersede) - (40ants-doc/commondoc/page::emit-search-page page)) - - (uiop:with-output-file (stream (uiop:merge-pathnames* #P"searchindex.js" absolute-dir) - :if-exists :supersede) - (write-string (40ants-doc/search::generate-search-index full-document page) - stream) - (terpri stream))) - - (loop with paths = '(("toc.js" "toc.js") - ("highlight/highlight.min.js" "highlight.min.js") - ("highlight/styles/atom-one-dark.min.css" "highlight.min.css") - ("search/searchtools.js" "searchtools.js") - ("search/language_data.js" "language_data.js") - ("search/doctools.js" "doctools.js") - ("underscore.js" "underscore.js") - ("jquery.js" "jquery.js")) - for (from to) in paths - do (uiop:copy-file (asdf:system-relative-pathname :40ants-doc - (concatenate 'string - "static/" from)) - (uiop:merge-pathnames* to absolute-dir))))) - - (unless (zerop num-warnings) - (warn "~A warning~:P ~A caught" - num-warnings - (if (= num-warnings 1) - "was" - "were"))) - (apply #'values - absolute-dir - (nreverse output-paths))))))) + (40ants-doc/themes/api::with-theme (theme) + (let* ((sections (uiop:ensure-list sections)) + (pages (mapcar #'40ants-doc/page:ensure-page sections)) + (page-documents (mapcar + #'40ants-doc/commondoc/builder:to-commondoc + pages)) + (full-document (process-document + (common-doc:make-document "Documentation" + :children page-documents) + :base-url base-url)) + (absolute-dir (uiop:ensure-absolute-pathname base-dir + (probe-file "."))) + (40ants-doc/commondoc/toc::*full-document* full-document) + (output-paths nil)) + + (ensure-directories-exist absolute-dir) + + (flet ((make-full-filename (page) + ;; PAGE argument could be either PAGE object or string denoting a relative path + ;; of HTML page. + (let* ((page-base-dir (or (when (typep page '40ants-doc/commondoc/page:page) + (page-base-dir page)) + base-dir)) + (absolute-dir (uiop:ensure-absolute-pathname page-base-dir + (probe-file "."))) + (filename (etypecase page + (40ants-doc/commondoc/page:page + (40ants-doc/commondoc/page::full-filename page)) + (string + page)))) + (uiop:merge-pathnames* filename absolute-dir)))) + (loop with global-format = format + for document in page-documents + for full-filename = (make-full-filename document) + for format = (or + ;; Page may override global format setting + (page-format document) + global-format) + do (ensure-directories-exist full-filename) + (uiop:with-output-file (stream full-filename + :if-exists :supersede) + (common-doc.format:emit-document (make-instance format) + document + stream) + (push full-filename output-paths))) + + (when (eql format + 'common-html:html) + (40ants-doc/themes/api::render-static absolute-dir) + + (let* ((page (40ants-doc/commondoc/page:make-page nil "search/index" + :title "Search Page" + :format :html)) + (filename (make-full-filename page))) + (ensure-directories-exist filename) + (uiop:with-output-file (common-html.emitter::*output-stream* + filename + :if-exists :supersede) + (40ants-doc/commondoc/page::emit-search-page page)) + + (uiop:with-output-file (stream (uiop:merge-pathnames* #P"searchindex.js" absolute-dir) + :if-exists :supersede) + (write-string (40ants-doc/search::generate-search-index full-document page) + stream) + (terpri stream))))) + + (unless (zerop num-warnings) + (warn "~A warning~:P ~A caught" + num-warnings + (if (= num-warnings 1) + "was" + "were"))) + (apply #'values + absolute-dir + (nreverse output-paths)))))))) (defvar *document-html-top-blocks-of-links* () diff --git a/src/themes/api.lisp b/src/themes/api.lisp index 12fa7c7c..3d507654 100644 --- a/src/themes/api.lisp +++ b/src/themes/api.lisp @@ -1,9 +1,50 @@ (uiop:define-package #:40ants-doc/themes/api (:use #:cl) - (:export - #:render-css)) + (:export #:render-css)) (in-package 40ants-doc/themes/api) +(defvar *theme*) + + +(defmacro with-theme ((theme) &body body) + (alexandria:once-only (theme) + `(let ((*theme* (typecase ,theme + (symbol (make-instance ,theme)) + (t ,theme)))) + ,@body))) + + (defgeneric render-css (theme) (:documentation "Returns a string with CSS.")) + + +(defun check-theme () + (unless (boundp '*theme*) + (error "Please, use WITH-THEME macro around the call"))) + + +(defun render-static (absolute-dir) + (check-theme) + + (let ((css-filename (uiop:merge-pathnames* #P"theme.css" absolute-dir))) + (uiop:with-output-file (stream css-filename + :if-exists :supersede) + (write-string (render-css *theme*) + stream) + (terpri stream)) + + ;; TODO: Probably let to override these files too + (loop with paths = '(("toc.js" "toc.js") + ("highlight/highlight.min.js" "highlight.min.js") + ("highlight/styles/atom-one-dark.min.css" "highlight.min.css") + ("search/searchtools.js" "searchtools.js") + ("search/language_data.js" "language_data.js") + ("search/doctools.js" "doctools.js") + ("underscore.js" "underscore.js") + ("jquery.js" "jquery.js")) + for (from to) in paths + do (uiop:copy-file (asdf:system-relative-pathname :40ants-doc + (concatenate 'string + "static/" from)) + (uiop:merge-pathnames* to absolute-dir))))) diff --git a/src/themes/default.lisp b/src/themes/default.lisp index 63bbec97..b6e45301 100644 --- a/src/themes/default.lisp +++ b/src/themes/default.lisp @@ -2,7 +2,9 @@ (:use #:cl) (:import-from #:40ants-doc/themes/api #:render-css) - (:import-from #:lass)) + (:import-from #:lass) + (:export + #:default-theme)) (in-package 40ants-doc/themes/default) @@ -205,6 +207,7 @@ (|#toc-footer| :margin-left 1.5em :margin-top 2em + :margin-bottom 1em (a :font-size 80% :color "#777777")) From 1d4c211ac4d48885f8395ec05ba732365f01c4b0 Mon Sep 17 00:00:00 2001 From: Alexander Artemenko Date: Wed, 1 Sep 2021 22:26:16 +0300 Subject: [PATCH 02/11] Page template was refactored into the multiple hooks. --- src/commondoc/page.lisp | 78 +------------------- src/themes/api.lisp | 58 ++++++++++++++- src/themes/default.lisp | 157 ++++++++++++++++++++++++++++++++++------ static/toc.js | 4 +- 4 files changed, 195 insertions(+), 102 deletions(-) diff --git a/src/commondoc/page.lisp b/src/commondoc/page.lisp index 734f3c30..2b64449e 100644 --- a/src/commondoc/page.lisp +++ b/src/commondoc/page.lisp @@ -38,6 +38,8 @@ (:import-from #:40ants-doc/dislocated-symbols #:dislocated-symbols #:supports-dislocated-symbols-p) + (:import-from #:40ants-doc/themes/api + #:with-page-template) (:export #:make-page #:page #:make-page-toc @@ -112,82 +114,6 @@ nil)) -(defun call-with-page-template (func uri title toc) - (check-type uri string) - - (let ((theme-uri (make-relative-path uri "theme.css")) - (highlight-css-uri (make-relative-path uri "highlight.min.css")) - (highlight-js-uri (make-relative-path uri "highlight.min.js")) - (jquery-uri (make-relative-path uri "jquery.js")) - (toc-js-uri (make-relative-path uri "toc.js"))) - - (with-html - (:html - (:head - (:meta :name "viewport" - :content "width=device-width, initial-scale=1") - (:title title) - (:link :rel "stylesheet" - :type "text/css" - :href theme-uri) - (:script :type "text/javascript" - :src jquery-uri) - (:script :type "text/javascript" - :src toc-js-uri) - (:link :rel "stylesheet" - :type "text/css" - :href highlight-css-uri) - (:script :type "text/javascript" - :src highlight-js-uri) - (:script "hljs.highlightAll();") - ;; MathJax configuration to display inline formulas - (:script - " - MathJax = { - tex: { - inlineMath: [['$','$']], - processEscapes: true - } - }; - ") - (:script :type "text/javascript" - :src "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js")) - (:body - (:div :id "content-container" - (when toc - (:div :id "toc" - (:form :method "GET" - :action (40ants-doc/rewrite::rewrite-url - (make-relative-path uri "search/index.html")) - :class "search" - (:input :type "text" - :name "q") - (:input :type "submit" - :value "Search") - (:span :id "search-progress")) - - (:div :id "page-toc" - (common-html.emitter::emit toc)) - (:div :id "toc-footer" - (:a :href "https://40ants.com/doc" - "[generated by 40ANTS-DOC]")))) - (:div :id "content" - ;; This role is required for Sphinx Doc's - ;; Javascript code. It searches texts inside - ;; the role[main] block - :role "main" - (funcall func)))))))) - - -(defmacro with-page-template ((uri title &key toc) &body body) - `(call-with-page-template - (lambda () - ,@body) - ,uri - ,title - ,toc)) - - (define-emitter (obj page) "Emit an piece of documentation." (with-page-template ((make-page-uri obj) diff --git a/src/themes/api.lisp b/src/themes/api.lisp index 3d507654..c947d9cd 100644 --- a/src/themes/api.lisp +++ b/src/themes/api.lisp @@ -1,6 +1,15 @@ (uiop:define-package #:40ants-doc/themes/api (:use #:cl) - (:export #:render-css)) + (:export #:render-css + #:render-page + #:render-html-head + #:render-toc + #:render-search-form + #:render-sidebar-footer + #:render-sidebar-header + #:render-sidebar + #:render-sidebar-content + #:render-content)) (in-package 40ants-doc/themes/api) @@ -18,6 +27,33 @@ (defgeneric render-css (theme) (:documentation "Returns a string with CSS.")) +(defgeneric render-page (theme uri title &key toc content) + (:documentation "Renders whole page using theme and callable CONTENT-FUNC.")) + +(defgeneric render-html-head (theme uri title) + (:documentation "Renders content of the HTML HEAD tag.")) + +(defgeneric render-content (theme uri toc content-func) + (:documentation "Renders page's content")) + +(defgeneric render-sidebar (theme uri toc) + (:documentation "Renders page's sidebar")) + +(defgeneric render-sidebar-header (theme uri toc) + (:documentation "Renders sidebar's header. Usually it contains a search input.")) + +(defgeneric render-sidebar-footer (theme uri toc) + (:documentation "Renders sidebar's header. By default it contains a link to the 40ANTS-DOC system.")) + +(defgeneric render-sidebar-content (theme uri toc) + (:documentation "Renders sidebar's content. By default it calls RENDER-TOC generic-function.")) + +(defgeneric render-toc (theme uri toc) + (:documentation "Renders documentation TOC.")) + +(defgeneric render-search-form (theme uri toc) + (:documentation "Renders a search form.")) + (defun check-theme () (unless (boundp '*theme*) @@ -48,3 +84,23 @@ (concatenate 'string "static/" from)) (uiop:merge-pathnames* to absolute-dir))))) + + +(defun call-with-page-template (func uri title toc) + (check-type uri string) + (check-theme) + (render-page *theme* uri title + :toc toc + :content func)) + + +(defmacro with-page-template ((uri title &key toc) &body body) + `(call-with-page-template + (lambda () + ,@body) + ,uri + ,title + ,toc)) + + + diff --git a/src/themes/default.lisp b/src/themes/default.lisp index b6e45301..ab2f9f29 100644 --- a/src/themes/default.lisp +++ b/src/themes/default.lisp @@ -3,6 +3,10 @@ (:import-from #:40ants-doc/themes/api #:render-css) (:import-from #:lass) + (:import-from #:40ants-doc/commondoc/html + #:with-html) + (:import-from #:40ants-doc/utils + #:make-relative-path) (:export #:default-theme)) (in-package 40ants-doc/themes/default) @@ -137,22 +141,17 @@ :background "#adff2f") ;; Content - (|#content-container| + + (.page :margin 0 :padding 0) - - (|#content| + + ((.page > .content) :margin-left 40ex :padding-left 2.5em :max-width 85ex) - - ;; Side-bar - - (form.search - :margin-left 1.5em - :margin-top 1.5em) - (|#toc| + (.sidebar :top 0px :left 0px :height 100% @@ -187,7 +186,23 @@ :background "#336699" :box-shadow inset -5px 0px 10px -5px "#000")) - (|#page-toc| + ((.sidebar > .header) + (a + :color "#777777")) + + ((.sidebar > .footer) + :margin-left 1.5em + :margin-top 2em + :margin-bottom 1em + (a + :font-size 80% + :color "#777777")) + + (form.search + :margin-left 1.5em + :margin-top 1.5em) + + (.page-toc (a :color "#fff")) @@ -200,18 +215,6 @@ (.menu-block-title :font-size 90%) - (|#toc-header| - (a - :color "#777777")) - - (|#toc-footer| - :margin-left 1.5em - :margin-top 2em - :margin-bottom 1em - (a - :font-size 80% - :color "#777777")) - (|#search-results| (.search (li @@ -219,3 +222,111 @@ (.unresolved-reference :color magenta)))) + + +(defmethod 40ants-doc/themes/api:render-page ((theme default-theme) uri title + &key toc content) + (with-html + (:html + (:head + (40ants-doc/themes/api:render-html-head theme uri title)) + (:body + (:div :class "page" + (40ants-doc/themes/api:render-sidebar theme uri toc) + (40ants-doc/themes/api:render-content theme uri toc content)))))) + + +(defmethod 40ants-doc/themes/api:render-html-head ((theme default-theme) uri title) + (let ((theme-uri (make-relative-path uri "theme.css")) + (highlight-css-uri (make-relative-path uri "highlight.min.css")) + (highlight-js-uri (make-relative-path uri "highlight.min.js")) + (jquery-uri (make-relative-path uri "jquery.js")) + (toc-js-uri (make-relative-path uri "toc.js"))) + (with-html + (:meta :name "viewport" + :content "width=device-width, initial-scale=1") + (:title title) + (:link :rel "stylesheet" + :type "text/css" + :href theme-uri) + (:script :type "text/javascript" + :src jquery-uri) + (:script :type "text/javascript" + :src toc-js-uri) + (:link :rel "stylesheet" + :type "text/css" + :href highlight-css-uri) + (:script :type "text/javascript" + :src highlight-js-uri) + (:script "hljs.highlightAll();") + ;; MathJax configuration to display inline formulas + (:script + " + MathJax = { + tex: { + inlineMath: [['$','$']], + processEscapes: true + } + }; + ") + (:script :type "text/javascript" + :src "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js")))) + + +(defmethod 40ants-doc/themes/api:render-content ((theme default-theme) uri toc content-func) + (declare (ignore uri toc)) + (with-html + (:div :class "content" + ;; This role is required for Sphinx Doc's + ;; Javascript code. It searches texts inside + ;; the role[main] block + :role "main" + (when content-func + (funcall content-func))))) + + +(defmethod 40ants-doc/themes/api:render-sidebar ((theme default-theme) uri toc) + (with-html + (:div :class "sidebar" + (40ants-doc/themes/api:render-sidebar-header theme uri toc) + (40ants-doc/themes/api:render-sidebar-content theme uri toc) + (40ants-doc/themes/api:render-sidebar-footer theme uri toc)))) + + +(defmethod 40ants-doc/themes/api:render-search-form ((theme default-theme) uri toc) + (with-html + (:form :method "GET" + :action (40ants-doc/rewrite::rewrite-url + (make-relative-path uri "search/index.html")) + :class "search" + (:input :type "text" + :name "q") + (:input :type "submit" + :value "Search") + (:span :id "search-progress")))) + + +(defmethod 40ants-doc/themes/api:render-toc ((theme default-theme) uri toc) + (with-html + (:div :class "page-toc" + (common-html.emitter::emit toc)))) + + +(defmethod 40ants-doc/themes/api:render-sidebar-header ((theme default-theme) uri toc) + (with-html + (:div :class "header" + (40ants-doc/themes/api:render-search-form theme uri toc)))) + + +(defmethod 40ants-doc/themes/api:render-sidebar-content ((theme default-theme) uri toc) + (with-html + (:div :class "content" + (40ants-doc/themes/api:render-toc theme uri toc)))) + + +(defmethod 40ants-doc/themes/api:render-sidebar-footer ((theme default-theme) uri toc) + (declare (ignore uri toc)) + (with-html + (:div :class "footer" + (:a :href "https://40ants.com/doc" + "[generated by 40ANTS-DOC]")))) diff --git a/static/toc.js b/static/toc.js index c7ffb4b3..5775fa21 100644 --- a/static/toc.js +++ b/static/toc.js @@ -3,7 +3,7 @@ $(document).ready(function() { $(window).scroll(function() { - $("#page-toc p").removeClass("toc-active"); + $(".page-toc p").removeClass("toc-active"); currentAnchor().addClass("toc-active"); }) }); @@ -31,7 +31,7 @@ var _anchors = null; function anchors() { if (!_anchors) { - _anchors = $("#page-toc a").map(function() { + _anchors = $(".page-toc a").map(function() { return $(this).attr("href"); }) } From e7fc7dc63da1367c947163146fda70f1948c355c Mon Sep 17 00:00:00 2001 From: Alexander Artemenko Date: Wed, 1 Sep 2021 23:13:28 +0300 Subject: [PATCH 03/11] Added page header and footer hooks. --- src/doc.lisp | 2 +- src/themes/api.lisp | 10 +++++++++- src/themes/default.lisp | 11 ++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/doc.lisp b/src/doc.lisp index 70229799..f30d2aed 100644 --- a/src/doc.lisp +++ b/src/doc.lisp @@ -62,7 +62,7 @@ (defparameter *badges* " - +
diff --git a/src/themes/api.lisp b/src/themes/api.lisp index c947d9cd..dea4839c 100644 --- a/src/themes/api.lisp +++ b/src/themes/api.lisp @@ -9,7 +9,9 @@ #:render-sidebar-header #:render-sidebar #:render-sidebar-content - #:render-content)) + #:render-content + #:render-page-header + #:render-page-footer)) (in-package 40ants-doc/themes/api) @@ -30,6 +32,12 @@ (defgeneric render-page (theme uri title &key toc content) (:documentation "Renders whole page using theme and callable CONTENT-FUNC.")) +(defgeneric render-page-header (theme uri title) + (:documentation "Renders whole page header. Does nothing by default.")) + +(defgeneric render-page-footer (theme uri) + (:documentation "Renders whole page footer. Does nothing by default.")) + (defgeneric render-html-head (theme uri title) (:documentation "Renders content of the HTML HEAD tag.")) diff --git a/src/themes/default.lisp b/src/themes/default.lisp index ab2f9f29..16c94085 100644 --- a/src/themes/default.lisp +++ b/src/themes/default.lisp @@ -232,8 +232,17 @@ (40ants-doc/themes/api:render-html-head theme uri title)) (:body (:div :class "page" + (40ants-doc/themes/api:render-page-header theme uri title) (40ants-doc/themes/api:render-sidebar theme uri toc) - (40ants-doc/themes/api:render-content theme uri toc content)))))) + (40ants-doc/themes/api:render-content theme uri toc content) + (40ants-doc/themes/api:render-page-footer theme uri)))))) + + +(defmethod 40ants-doc/themes/api:render-page-header ((theme default-theme) uri title) + (declare (ignore uri title))) + +(defmethod 40ants-doc/themes/api:render-page-footer ((theme default-theme) uri) + (declare (ignore uri))) (defmethod 40ants-doc/themes/api:render-html-head ((theme default-theme) uri title) From adc56394fe35f1287880d2c34593d84ccae47561 Mon Sep 17 00:00:00 2001 From: Alexander Artemenko Date: Thu, 2 Sep 2021 20:23:39 +0300 Subject: [PATCH 04/11] Added a way to define highlighted languages and theme. --- src/builder.lisp | 14 +- src/highlight.lisp | 295 ++++++++++ src/themes/api.lisp | 29 +- src/themes/default.lisp | 5 + static/README.md | 25 - static/highlight/LICENSE | 29 - static/highlight/highlight.min.js | 512 ------------------ static/highlight/styles/atom-one-dark.min.css | 1 - 8 files changed, 336 insertions(+), 574 deletions(-) create mode 100644 src/highlight.lisp delete mode 100644 static/README.md delete mode 100644 static/highlight/LICENSE delete mode 100644 static/highlight/highlight.min.js delete mode 100644 static/highlight/styles/atom-one-dark.min.css diff --git a/src/builder.lisp b/src/builder.lisp index 7adbe305..5821b595 100644 --- a/src/builder.lisp +++ b/src/builder.lisp @@ -106,7 +106,9 @@ (base-url nil) (docs-dir #P"docs/") (clean-urls 40ants-doc/rewrite::*clean-urls*) - (downcase-uppercase-code 40ants-doc/builder/vars::*downcase-uppercase-code*)) + (downcase-uppercase-code 40ants-doc/builder/vars::*downcase-uppercase-code*) + highlight-languages + highlight-theme) "Generate pretty HTML documentation for a single ASDF system, possibly linking to github. If you are migrating from MGL-PAX, then note, this function replaces UPDATE-ASDF-SYSTEM-HTML-DOCS @@ -170,6 +172,8 @@ :clean-urls clean-urls :downcase-uppercase-code downcase-uppercase-code :theme theme + :highlight-languages highlight-languages + :highlight-theme highlight-theme :format :html)) ;;; Generate with the default HTML look @@ -221,7 +225,9 @@ (warn-on-undocumented-packages 40ants-doc/commondoc/page::*warn-on-undocumented-packages*) (clean-urls 40ants-doc/rewrite::*clean-urls*) (downcase-uppercase-code 40ants-doc/builder/vars::*downcase-uppercase-code*) - (format :html)) + (format :html) + highlight-languages + highlight-theme) "Renders given sections or pages into a files on disk. By default, it renders in to HTML, but you can specify FORMAT argument. @@ -307,7 +313,9 @@ (when (eql format 'common-html:html) - (40ants-doc/themes/api::render-static absolute-dir) + (40ants-doc/themes/api::render-static absolute-dir + :highlight-languages highlight-languages + :highlight-theme highlight-theme) (let* ((page (40ants-doc/commondoc/page:make-page nil "search/index" :title "Search Page" diff --git a/src/highlight.lisp b/src/highlight.lisp new file mode 100644 index 00000000..53b591a7 --- /dev/null +++ b/src/highlight.lisp @@ -0,0 +1,295 @@ +(defpackage #:40ants-doc/highlight + (:use #:cl) + (:import-from #:dexador) + (:import-from #:log4cl) + (:import-from #:alexandria + #:when-let) + (:import-from #:cl-cookie + #:cookie-value + #:cookie-name + #:make-cookie-jar + #:cookie-jar-cookies) + (:import-from #:tmpdir + #:with-tmpdir)) +(in-package 40ants-doc/highlight) + + +(defvar *supported-languages* + '("1c" + "abnf" + "accesslog" + "actionscript" + "ada" + "angelscript" + "apache" + "applescript" + "arcade" + "arduino" + "armasm" + "asciidoc" + "aspectj" + "autohotkey" + "autoit" + "avrasm" + "awk" + "axapta" + "bash" + "basic" + "bnf" + "brainfuck" + "c" + "cal" + "capnproto" + "ceylon" + "clean" + "clojure-repl" + "clojure" + "cmake" + "coffeescript" + "coq" + "cos" + "cpp" + "crmsh" + "crystal" + "csharp" + "csp" + "css" + "d" + "dart" + "delphi" + "diff" + "django" + "dns" + "dockerfile" + "dos" + "dsconfig" + "dts" + "dust" + "ebnf" + "elixir" + "elm" + "erb" + "erlang-repl" + "erlang" + "excel" + "fix" + "flix" + "fortran" + "fsharp" + "gams" + "gauss" + "gcode" + "gherkin" + "glsl" + "gml" + "go" + "golo" + "gradle" + "groovy" + "haml" + "handlebars" + "haskell" + "haxe" + "hsp" + "http" + "hy" + "inform7" + "ini" + "irpf90" + "isbl" + "java" + "javascript" + "jboss-cli" + "json" + "julia-repl" + "julia" + "kotlin" + "lasso" + "latex" + "ldif" + "leaf" + "less" + "lisp" + "livecodeserver" + "livescript" + "llvm" + "lsl" + "lua" + "makefile" + "markdown" + "mathematica" + "matlab" + "maxima" + "mel" + "mercury" + "mipsasm" + "mizar" + "mojolicious" + "monkey" + "moonscript" + "n1ql" + "nestedtext" + "nginx" + "nim" + "nix" + "node-repl" + "nsis" + "objectivec" + "ocaml" + "openscad" + "oxygene" + "parser3" + "perl" + "pf" + "pgsql" + "php-template" + "php" + "plaintext" + "pony" + "powershell" + "processing" + "profile" + "prolog" + "properties" + "protobuf" + "puppet" + "purebasic" + "python-repl" + "python" + "q" + "qml" + "r" + "reasonml" + "rib" + "roboconf" + "routeros" + "rsl" + "ruby" + "ruleslanguage" + "rust" + "sas" + "scala" + "scheme" + "scilab" + "scss" + "shell" + "smali" + "smalltalk" + "sml" + "sqf" + "sql" + "stan" + "stata" + "step21" + "stylus" + "subunit" + "swift" + "taggerscript" + "tap" + "tcl" + "thrift" + "tp" + "twig" + "typescript" + "vala" + "vbnet" + "vbscript-html" + "vbscript" + "verilog" + "vhdl" + "vim" + "wasm" + "wren" + "x86asm" + "xl" + "xml" + "xquery" + "yaml" + "zephir")) + + +(defun to-downcased-string (thing) + (string-downcase + (etypecase thing + (symbol (symbol-name thing)) + (string thing)))) + +(defun normalize (lang) + (let ((result (to-downcased-string lang))) + (unless (member result *supported-languages* :test #'string=) + (error "Language \"~A\" is not supported by highlight.js" + result)) + result)) + +(defun normalize-langs (languages) + (let* ((languages (if (eql languages :all) + *supported-languages* + (uiop:ensure-list languages))) + (normalized (mapcar #'normalize languages)) + (sorted (sort normalized + #'string<))) + sorted)) + +(defun generate-meta-data (languages theme) + (format nil "languages: ~{~a~^, ~}~%theme: ~A~%" + languages + (to-downcased-string theme))) + +(defun download-highlight-js (languages &key (to "./") + (theme "default")) + (with-tmpdir (tmpdir) + (let* ((languages (normalize-langs languages)) + (to (uiop:ensure-directory-pathname to)) + (metadata-path (uiop:merge-pathnames* "METADATA" + to)) + (metadata (generate-meta-data languages theme))) + + (cond + ((and (probe-file metadata-path) + (string= (alexandria:read-file-into-string metadata-path) + metadata)) + (log:info "METADATA file lists same languages and theme. Skipping download of Highlight.js")) + (t + (log:info "Downloading Highlight.js") + (let* ((url "https://highlightjs.org/download/") + (jar (make-cookie-jar)) + (cookies (progn (dex:get url :cookie-jar jar) + (cookie-jar-cookies jar))) + (csrftoken (when-let ((cookie (find "csrftoken" cookies + :key #'cookie-name + :test #'string-equal))) + (cookie-value cookie))) + (post-data (append (list (cons "csrfmiddlewaretoken" csrftoken)) + (loop for lang in languages + for normalized-lang = (normalize lang) + collect (cons (format nil "~A.js" lang) + "on")))) + (headers (list (cons "Referer" url))) + (response (dex:post url + :content post-data + :headers headers + :cookie-jar jar)) + (path (uiop:merge-pathnames* #P"archive.zip" tmpdir))) + + (ensure-directories-exist path) + (ensure-directories-exist to) + + (alexandria:write-byte-vector-into-file response path + :if-exists :supersede) + (trivial-extract:extract-zip path) + + (uiop:copy-file (uiop:merge-pathnames* "highlight.min.js" tmpdir) + (uiop:merge-pathnames* "highlight.min.js" to)) + + (let* ((theme (to-downcased-string theme)) + (theme-path (uiop:merge-pathnames* (format nil "styles/~A.min.css" theme) + tmpdir))) + (unless (probe-file theme-path) + (error "Theme \"~A\" was is not supported by Highlight.js" + theme)) + (uiop:copy-file theme-path + (uiop:merge-pathnames* "highlight.min.css" to))) + + (alexandria:write-string-into-file metadata metadata-path + :if-exists :supersede)))))) + (values)) diff --git a/src/themes/api.lisp b/src/themes/api.lisp index dea4839c..80d5aade 100644 --- a/src/themes/api.lisp +++ b/src/themes/api.lisp @@ -1,5 +1,7 @@ (uiop:define-package #:40ants-doc/themes/api (:use #:cl) + (:import-from #:40ants-doc/highlight + #:download-highlight-js) (:export #:render-css #:render-page #:render-html-head @@ -11,7 +13,9 @@ #:render-sidebar-content #:render-content #:render-page-header - #:render-page-footer)) + #:render-page-footer + #:highlight-languages + #:highlight-theme)) (in-package 40ants-doc/themes/api) @@ -26,6 +30,19 @@ ,@body))) +(defgeneric highlight-languages (theme) + (:documentation "Returns a list of languages to highlight in snippets. Each language should be supported by Highlight.js.") + (:method ((theme t)) + (list :lisp + :bash))) + +(defgeneric highlight-theme (theme) + (:documentation "Returns a string with the name of the Highlight.js color theme for highlighted snippets. + + To preview themes, use this site: https://highlightjs.org/static/demo/") + (:method ((theme t)) + "magula")) + (defgeneric render-css (theme) (:documentation "Returns a string with CSS.")) @@ -68,7 +85,7 @@ (error "Please, use WITH-THEME macro around the call"))) -(defun render-static (absolute-dir) +(defun render-static (absolute-dir &key highlight-languages highlight-theme) (check-theme) (let ((css-filename (uiop:merge-pathnames* #P"theme.css" absolute-dir))) @@ -78,10 +95,14 @@ stream) (terpri stream)) + (download-highlight-js (or highlight-languages + (highlight-languages *theme*)) + :to absolute-dir + :theme (or highlight-theme + (highlight-theme *theme*))) + ;; TODO: Probably let to override these files too (loop with paths = '(("toc.js" "toc.js") - ("highlight/highlight.min.js" "highlight.min.js") - ("highlight/styles/atom-one-dark.min.css" "highlight.min.css") ("search/searchtools.js" "searchtools.js") ("search/language_data.js" "language_data.js") ("search/doctools.js" "doctools.js") diff --git a/src/themes/default.lisp b/src/themes/default.lisp index 16c94085..e58aa723 100644 --- a/src/themes/default.lisp +++ b/src/themes/default.lisp @@ -223,6 +223,11 @@ (.unresolved-reference :color magenta)))) +(defmethod 40ants-doc/themes/api:highlight-languages ((theme default-theme)) + '("lisp" "bash" "css" "json" "yaml" "plaintext" "xml" "markdown")) + +(defmethod 40ants-doc/themes/api:highlight-theme ((theme default-theme)) + "atom-one-dark") (defmethod 40ants-doc/themes/api:render-page ((theme default-theme) uri title &key toc content) diff --git a/static/README.md b/static/README.md deleted file mode 100644 index b8c5c9bd..00000000 --- a/static/README.md +++ /dev/null @@ -1,25 +0,0 @@ -How to update highlight.js -========================== - -This folder contains subfolder *highlight*, downloaded from -https://highlightjs.org/download/. Version, included into -the repository, supports these languages: - -* bash -* css -* json -* yaml -* plain-text -* html -* markdown -* lisp - -By default, *atom-one-dark.min.css* theme is used. - -If you want to include other languages or themes, go to the -https://highlightjs.org/download/, download archive and unpack it -into this *static* directory. Strip down unnecessary files, -to make ASDF system smaller. You can remove everything except -*highlight.min.js*, *styles/.min.css* and *LICENSE*. - -Different themes can be previewed at https://highlightjs.org/static/demo/. diff --git a/static/highlight/LICENSE b/static/highlight/LICENSE deleted file mode 100644 index 2250cc7e..00000000 --- a/static/highlight/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2006, Ivan Sagalaev. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/highlight/highlight.min.js b/static/highlight/highlight.min.js deleted file mode 100644 index 0edc9a13..00000000 --- a/static/highlight/highlight.min.js +++ /dev/null @@ -1,512 +0,0 @@ -/*! - Highlight.js v11.0.1 (git: 1cf31f015d) - (c) 2006-2021 Ivan Sagalaev and other contributors - License: BSD-3-Clause - */ -var hljs=function(){"use strict";var e={exports:{}};function t(e){ -return e instanceof Map?e.clear=e.delete=e.set=()=>{ -throw Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{ -throw Error("set is read-only") -}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach((n=>{var i=e[n] -;"object"!=typeof i||Object.isFrozen(i)||t(i)})),e} -e.exports=t,e.exports.default=t;var n=e.exports;class i{constructor(e){ -void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} -ignoreMatch(){this.isMatchIgnored=!0}}function r(e){ -return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") -}function s(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] -;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const o=e=>!!e.kind -;class a{constructor(e,t){ -this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ -this.buffer+=r(e)}openNode(e){if(!o(e))return;let t=e.kind -;t=e.sublanguage?"language-"+t:((e,{prefix:t})=>{if(e.includes(".")){ -const n=e.split(".") -;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") -}return`${t}${e}`})(t,{prefix:this.classPrefix}),this.span(t)}closeNode(e){ -o(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ -this.buffer+=``}}class l{constructor(){this.rootNode={ -children:[]},this.stack=[this.rootNode]}get top(){ -return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ -this.top.children.push(e)}openNode(e){const t={kind:e,children:[]} -;this.add(t),this.stack.push(t)}closeNode(){ -if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ -for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} -walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ -return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), -t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ -"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ -l._collapse(e)})))}}class c extends l{constructor(e){super(),this.options=e} -addKeyword(e,t){""!==e&&(this.openNode(t),this.addText(e),this.closeNode())} -addText(e){""!==e&&this.add(e)}addSublanguage(e,t){const n=e.root -;n.kind=t,n.sublanguage=!0,this.add(n)}toHTML(){ -return new a(this,this.options).value()}finalize(){return!0}}function g(e){ -return e?"string"==typeof e?e:e.source:null}function d(...e){ -return e.map((e=>g(e))).join("")}function u(...e){return"("+((e=>{ -const t=e[e.length-1] -;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} -})(e).capture?"":"?:")+e.map((e=>g(e))).join("|")+")"}function h(e){ -return RegExp(e.toString()+"|").exec("").length-1} -const f=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ -;function p(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n -;let i=g(e),r="";for(;i.length>0;){const e=f.exec(i);if(!e){r+=i;break} -r+=i.substring(0,e.index), -i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?r+="\\"+(Number(e[1])+t):(r+=e[0], -"("===e[0]&&n++)}return r})).map((e=>`(${e})`)).join(t)} -const b="[a-zA-Z]\\w*",m="[a-zA-Z_]\\w*",E="\\b\\d+(\\.\\d+)?",x="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",y="\\b(0b[01]+)",w={ -begin:"\\\\[\\s\\S]",relevance:0},_={scope:"string",begin:"'",end:"'", -illegal:"\\n",contains:[w]},v={scope:"string",begin:'"',end:'"',illegal:"\\n", -contains:[w]},O=(e,t,n={})=>{const i=s({scope:"comment",begin:e,end:t, -contains:[]},n);i.contains.push({scope:"doctag", -begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", -end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) -;const r=u("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) -;return i.contains.push({begin:d(/[ ]+/,"(",r,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),i -},k=O("//","$"),N=O("/\\*","\\*/"),S=O("#","$");var M=Object.freeze({ -__proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:b,UNDERSCORE_IDENT_RE:m, -NUMBER_RE:E,C_NUMBER_RE:x,BINARY_NUMBER_RE:y, -RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", -SHEBANG:(e={})=>{const t=/^#![ ]*\// -;return e.binary&&(e.begin=d(t,/.*\b/,e.binary,/\b.*/)),s({scope:"meta",begin:t, -end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, -BACKSLASH_ESCAPE:w,APOS_STRING_MODE:_,QUOTE_STRING_MODE:v,PHRASAL_WORDS_MODE:{ -begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ -},COMMENT:O,C_LINE_COMMENT_MODE:k,C_BLOCK_COMMENT_MODE:N,HASH_COMMENT_MODE:S, -NUMBER_MODE:{scope:"number",begin:E,relevance:0},C_NUMBER_MODE:{scope:"number", -begin:x,relevance:0},BINARY_NUMBER_MODE:{scope:"number",begin:y,relevance:0}, -REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{scope:"regexp",begin:/\//, -end:/\/[gimuy]*/,illegal:/\n/,contains:[w,{begin:/\[/,end:/\]/,relevance:0, -contains:[w]}]}]},TITLE_MODE:{scope:"title",begin:b,relevance:0}, -UNDERSCORE_TITLE_MODE:{scope:"title",begin:m,relevance:0},METHOD_GUARD:{ -begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{ -"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ -t.data._beginMatch!==e[1]&&t.ignoreMatch()}})});function R(e,t){ -"."===e.input[e.index-1]&&t.ignoreMatch()}function j(e,t){ -void 0!==e.className&&(e.scope=e.className,delete e.className)}function A(e,t){ -t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", -e.__beforeBegin=R,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, -void 0===e.relevance&&(e.relevance=0))}function I(e,t){ -Array.isArray(e.illegal)&&(e.illegal=u(...e.illegal))}function B(e,t){ -if(e.match){ -if(e.begin||e.end)throw Error("begin & end are not supported with match") -;e.begin=e.match,delete e.match}}function T(e,t){ -void 0===e.relevance&&(e.relevance=1)}const L=(e,t)=>{if(!e.beforeMatch)return -;if(e.starts)throw Error("beforeMatch cannot be used with starts") -;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] -})),e.keywords=n.keywords, -e.begin=d(n.beforeMatch,d("(?=",n.begin,")")),e.starts={relevance:0, -contains:[Object.assign(n,{endsParent:!0})]},e.relevance=0,delete n.beforeMatch -},D=["of","and","for","in","not","or","if","then","parent","list","value"] -;function P(e,t,n="keyword"){const i=Object.create(null) -;return"string"==typeof e?r(n,e.split(" ")):Array.isArray(e)?r(n,e):Object.keys(e).forEach((n=>{ -Object.assign(i,P(e[n],t,n))})),i;function r(e,n){ -t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") -;i[n[0]]=[e,C(n[0],n[1])]}))}}function C(e,t){ -return t?Number(t):(e=>D.includes(e.toLowerCase()))(e)?0:1}const H={},$=e=>{ -console.error(e)},U=(e,...t)=>{console.log("WARN: "+e,...t)},z=(e,t)=>{ -H[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),H[`${e}/${t}`]=!0) -},K=Error();function W(e,t,{key:n}){let i=0;const r=e[n],s={},o={} -;for(let e=1;e<=t.length;e++)o[e+i]=r[e],s[e+i]=!0,i+=h(t[e-1]) -;e[n]=o,e[n]._emit=s,e[n]._multi=!0}function X(e){(e=>{ -e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, -delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ -_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope -}),(e=>{if(Array.isArray(e.begin)){ -if(e.skip||e.excludeBegin||e.returnBegin)throw $("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), -K -;if("object"!=typeof e.beginScope||null===e.beginScope)throw $("beginScope must be object"), -K;W(e,e.begin,{key:"beginScope"}),e.begin=p(e.begin,{joinWith:""})}})(e),(e=>{ -if(Array.isArray(e.end)){ -if(e.skip||e.excludeEnd||e.returnEnd)throw $("skip, excludeEnd, returnEnd not compatible with endScope: {}"), -K -;if("object"!=typeof e.endScope||null===e.endScope)throw $("endScope must be object"), -K;W(e,e.end,{key:"endScope"}),e.end=p(e.end,{joinWith:""})}})(e)}function G(e){ -function t(t,n){return RegExp(g(t),"m"+(e.case_insensitive?"i":"")+(n?"g":""))} -class n{constructor(){ -this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} -addRule(e,t){ -t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), -this.matchAt+=h(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) -;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(p(e,{joinWith:"|" -}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex -;const t=this.matcherRe.exec(e);if(!t)return null -;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] -;return t.splice(0,n),Object.assign(t,i)}}class i{constructor(){ -this.rules=[],this.multiRegexes=[], -this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ -if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n -;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), -t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ -return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ -this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ -const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex -;let n=t.exec(e) -;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ -const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} -return n&&(this.regexIndex+=n.position+1, -this.regexIndex===this.count&&this.considerAll()),n}} -if(e.compilerExtensions||(e.compilerExtensions=[]), -e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") -;return e.classNameAliases=s(e.classNameAliases||{}),function n(r,o){const a=r -;if(r.isCompiled)return a -;[j,B,X,L].forEach((e=>e(r,o))),e.compilerExtensions.forEach((e=>e(r,o))), -r.__beforeBegin=null,[A,I,T].forEach((e=>e(r,o))),r.isCompiled=!0;let l=null -;return"object"==typeof r.keywords&&r.keywords.$pattern&&(r.keywords=Object.assign({},r.keywords), -l=r.keywords.$pattern, -delete r.keywords.$pattern),l=l||/\w+/,r.keywords&&(r.keywords=P(r.keywords,e.case_insensitive)), -a.keywordPatternRe=t(l,!0), -o&&(r.begin||(r.begin=/\B|\b/),a.beginRe=t(r.begin),r.end||r.endsWithParent||(r.end=/\B|\b/), -r.end&&(a.endRe=t(r.end)), -a.terminatorEnd=g(r.end)||"",r.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(r.end?"|":"")+o.terminatorEnd)), -r.illegal&&(a.illegalRe=t(r.illegal)), -r.contains||(r.contains=[]),r.contains=[].concat(...r.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>s(e,{ -variants:null},t)))),e.cachedVariants?e.cachedVariants:Z(e)?s(e,{ -starts:e.starts?s(e.starts):null -}):Object.isFrozen(e)?s(e):e))("self"===e?r:e)))),r.contains.forEach((e=>{n(e,a) -})),r.starts&&n(r.starts,o),a.matcher=(e=>{const t=new i -;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" -}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" -}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function Z(e){ -return!!e&&(e.endsWithParent||Z(e.starts))}const F=r,V=s,q=Symbol("nomatch") -;var J=(e=>{const t=Object.create(null),r=Object.create(null),s=[];let o=!0 -;const a="Could not find the language '{}', did you forget to load/include a language module?",l={ -disableAutodetect:!0,name:"Plain text",contains:[]};let g={ -ignoreUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, -languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", -cssSelector:"pre code",languages:null,__emitter:c};function d(e){ -return g.noHighlightRe.test(e)}function u(e,t,n,i){let r="",s="" -;"object"==typeof t?(r=e, -n=t.ignoreIllegals,s=t.language,i=void 0):(z("10.7.0","highlight(lang, code, ...args) has been deprecated."), -z("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), -s=e,r=t),void 0===n&&(n=!0);const o={code:r,language:s};w("before:highlight",o) -;const a=o.result?o.result:h(o.language,o.code,n,i) -;return a.code=o.code,w("after:highlight",a),a}function h(e,n,r,s){ -const l=Object.create(null);function c(){if(!k.keywords)return void S.addText(M) -;let e=0;k.keywordPatternRe.lastIndex=0;let t=k.keywordPatternRe.exec(M),n="" -;for(;t;){n+=M.substring(e,t.index) -;const r=_.case_insensitive?t[0].toLowerCase():t[0],s=(i=r,k.keywords[i]);if(s){ -const[e,i]=s -;if(S.addText(n),n="",l[r]=(l[r]||0)+1,l[r]<=7&&(R+=i),e.startsWith("_"))n+=t[0];else{ -const n=_.classNameAliases[e]||e;S.addKeyword(t[0],n)}}else n+=t[0] -;e=k.keywordPatternRe.lastIndex,t=k.keywordPatternRe.exec(M)}var i -;n+=M.substr(e),S.addText(n)}function d(){null!=k.subLanguage?(()=>{ -if(""===M)return;let e=null;if("string"==typeof k.subLanguage){ -if(!t[k.subLanguage])return void S.addText(M) -;e=h(k.subLanguage,M,!0,N[k.subLanguage]),N[k.subLanguage]=e._top -}else e=f(M,k.subLanguage.length?k.subLanguage:null) -;k.relevance>0&&(R+=e.relevance),S.addSublanguage(e._emitter,e.language) -})():c(),M=""}function u(e,t){let n=1;for(;void 0!==t[n];){if(!e._emit[n]){n++ -;continue}const i=_.classNameAliases[e[n]]||e[n],r=t[n] -;i?S.addKeyword(r,i):(M=r,c(),M=""),n++}}function p(e,t){ -return e.scope&&"string"==typeof e.scope&&S.openNode(_.classNameAliases[e.scope]||e.scope), -e.beginScope&&(e.beginScope._wrap?(S.addKeyword(M,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), -M=""):e.beginScope._multi&&(u(e.beginScope,t),M="")),k=Object.create(e,{parent:{ -value:k}}),k}function b(e,t,n){let r=((e,t)=>{const n=e&&e.exec(t) -;return n&&0===n.index})(e.endRe,n);if(r){if(e["on:end"]){const n=new i(e) -;e["on:end"](t,n),n.isMatchIgnored&&(r=!1)}if(r){ -for(;e.endsParent&&e.parent;)e=e.parent;return e}} -if(e.endsWithParent)return b(e.parent,t,n)}function m(e){ -return 0===k.matcher.regexIndex?(M+=e[0],1):(I=!0,0)}function x(e){ -const t=e[0],i=n.substr(e.index),r=b(k,e,i);if(!r)return q;const s=k -;k.endScope&&k.endScope._wrap?(d(), -S.addKeyword(t,k.endScope._wrap)):k.endScope&&k.endScope._multi?(d(), -u(k.endScope,e)):s.skip?M+=t:(s.returnEnd||s.excludeEnd||(M+=t), -d(),s.excludeEnd&&(M=t));do{ -k.scope&&!k.isMultiClass&&S.closeNode(),k.skip||k.subLanguage||(R+=k.relevance), -k=k.parent}while(k!==r.parent) -;return r.starts&&p(r.starts,e),s.returnEnd?0:t.length}let y={};function w(t,s){ -const a=s&&s[0];if(M+=t,null==a)return d(),0 -;if("begin"===y.type&&"end"===s.type&&y.index===s.index&&""===a){ -if(M+=n.slice(s.index,s.index+1),!o){const t=Error(`0 width match regex (${e})`) -;throw t.languageName=e,t.badRule=y.rule,t}return 1} -if(y=s,"begin"===s.type)return(e=>{ -const t=e[0],n=e.rule,r=new i(n),s=[n.__beforeBegin,n["on:begin"]] -;for(const n of s)if(n&&(n(e,r),r.isMatchIgnored))return m(t) -;return n.skip?M+=t:(n.excludeBegin&&(M+=t), -d(),n.returnBegin||n.excludeBegin||(M=t)),p(n,e),n.returnBegin?0:t.length})(s) -;if("illegal"===s.type&&!r){ -const e=Error('Illegal lexeme "'+a+'" for mode "'+(k.scope||"")+'"') -;throw e.mode=k,e}if("end"===s.type){const e=x(s);if(e!==q)return e} -if("illegal"===s.type&&""===a)return 1 -;if(A>1e5&&A>3*s.index)throw Error("potential infinite loop, way more iterations than matches") -;return M+=a,a.length}const _=E(e) -;if(!_)throw $(a.replace("{}",e)),Error('Unknown language: "'+e+'"') -;const v=G(_);let O="",k=s||v;const N={},S=new g.__emitter(g);(()=>{const e=[] -;for(let t=k;t!==_;t=t.parent)t.scope&&e.unshift(t.scope) -;e.forEach((e=>S.openNode(e)))})();let M="",R=0,j=0,A=0,I=!1;try{ -for(k.matcher.considerAll();;){ -A++,I?I=!1:k.matcher.considerAll(),k.matcher.lastIndex=j -;const e=k.matcher.exec(n);if(!e)break;const t=w(n.substring(j,e.index),e) -;j=e.index+t}return w(n.substr(j)),S.closeAllNodes(),S.finalize(),O=S.toHTML(),{ -language:e,value:O,relevance:R,illegal:!1,_emitter:S,_top:k}}catch(t){ -if(t.message&&t.message.includes("Illegal"))return{language:e,value:F(n), -illegal:!0,relevance:0,_illegalBy:{message:t.message,index:j, -context:n.slice(j-100,j+100),mode:t.mode,resultSoFar:O},_emitter:S};if(o)return{ -language:e,value:F(n),illegal:!1,relevance:0,errorRaised:t,_emitter:S,_top:k} -;throw t}}function f(e,n){n=n||g.languages||Object.keys(t);const i=(e=>{ -const t={value:F(e),illegal:!1,relevance:0,_top:l,_emitter:new g.__emitter(g)} -;return t._emitter.addText(e),t})(e),r=n.filter(E).filter(y).map((t=>h(t,e,!1))) -;r.unshift(i);const s=r.sort(((e,t)=>{ -if(e.relevance!==t.relevance)return t.relevance-e.relevance -;if(e.language&&t.language){if(E(e.language).supersetOf===t.language)return 1 -;if(E(t.language).supersetOf===e.language)return-1}return 0})),[o,a]=s,c=o -;return c.secondBest=a,c}function p(e){let t=null;const n=(e=>{ -let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" -;const n=g.languageDetectRe.exec(t);if(n){const t=E(n[1]) -;return t||(U(a.replace("{}",n[1])), -U("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} -return t.split(/\s+/).find((e=>d(e)||E(e)))})(e);if(d(n))return -;w("before:highlightElement",{el:e,language:n -}),!g.ignoreUnescapedHTML&&e.children.length>0&&(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), -console.warn("https://github.com/highlightjs/highlight.js/issues/2886"), -console.warn(e)),t=e;const i=t.textContent,s=n?u(i,{language:n,ignoreIllegals:!0 -}):f(i);e.innerHTML=s.value,((e,t,n)=>{const i=t&&r[t]||n -;e.classList.add("hljs"),e.classList.add("language-"+i) -})(e,n,s.language),e.result={language:s.language,re:s.relevance, -relevance:s.relevance},s.secondBest&&(e.secondBest={ -language:s.secondBest.language,relevance:s.secondBest.relevance -}),w("after:highlightElement",{el:e,result:s,text:i})}let b=!1;function m(){ -"loading"!==document.readyState?document.querySelectorAll(g.cssSelector).forEach(p):b=!0 -}function E(e){return e=(e||"").toLowerCase(),t[e]||t[r[e]]} -function x(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ -r[e.toLowerCase()]=t}))}function y(e){const t=E(e) -;return t&&!t.disableAutodetect}function w(e,t){const n=e;s.forEach((e=>{ -e[n]&&e[n](t)}))} -"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ -b&&m()}),!1),Object.assign(e,{highlight:u,highlightAuto:f,highlightAll:m, -highlightElement:p, -highlightBlock:e=>(z("10.7.0","highlightBlock will be removed entirely in v12.0"), -z("10.7.0","Please use highlightElement now."),p(e)),configure:e=>{g=V(g,e)}, -initHighlighting:()=>{ -m(),z("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, -initHighlightingOnLoad:()=>{ -m(),z("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") -},registerLanguage:(n,i)=>{let r=null;try{r=i(e)}catch(e){ -if($("Language definition for '{}' could not be registered.".replace("{}",n)), -!o)throw e;$(e),r=l} -r.name||(r.name=n),t[n]=r,r.rawDefinition=i.bind(null,e),r.aliases&&x(r.aliases,{ -languageName:n})},unregisterLanguage:e=>{delete t[e] -;for(const t of Object.keys(r))r[t]===e&&delete r[t]}, -listLanguages:()=>Object.keys(t),getLanguage:E,registerAliases:x, -autoDetection:y,inherit:V,addPlugin:e=>{(e=>{ -e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ -e["before:highlightBlock"](Object.assign({block:t.el},t)) -}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ -e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),s.push(e)} -}),e.debugMode=()=>{o=!1},e.safeMode=()=>{o=!0},e.versionString="11.0.1" -;for(const e in M)"object"==typeof M[e]&&n(M[e]);return Object.assign(e,M),e -})({}),Y=Object.freeze({__proto__:null});const Q=J -;for(const e of Object.keys(Y)){const t=e.replace("grmr_","") -;Q.registerLanguage(t,Y[e])}return Q}() -;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);hljs.registerLanguage("ruby",(()=>{"use strict";function e(e){ -return n("(?=",e,")")}function n(...e){return e.map((e=>{ -return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return a=>{ -const i="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",s={ -keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor __FILE__", -built_in:"proc lambda",literal:"true false nil"},r={className:"doctag", -begin:"@[A-Za-z]+"},b={begin:"#<",end:">"},c=[a.COMMENT("#","$",{contains:[r] -}),a.COMMENT("^=begin","^=end",{contains:[r],relevance:10 -}),a.COMMENT("^__END__","\\n$")],t={className:"subst",begin:/#\{/,end:/\}/, -keywords:s},g={className:"string",contains:[a.BACKSLASH_ESCAPE,t],variants:[{ -begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/, -end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{ -begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/, -end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{ -begin:/\B\?(\\\d{1,3})/},{begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{ -begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{ -begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{ -begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{ -begin:n(/<<[-~]?'?/,e(/(\w+)(?=\W)[^\n]*\n(?:[^\n]*\n)*?\s*\1\b/)), -contains:[a.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/, -contains:[a.BACKSLASH_ESCAPE,t]})]}]},d="[0-9](_?[0-9])*",l={className:"number", -relevance:0,variants:[{ -begin:`\\b([1-9](_?[0-9])*|0)(\\.(${d}))?([eE][+-]?(${d})|r)?i?\\b`},{ -begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b" -},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{ -begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{ -begin:"\\b0(_?[0-7])+r?i?\\b"}]},o={className:"params",begin:"\\(",end:"\\)", -endsParent:!0,keywords:s},_=[g,{className:"class",beginKeywords:"class module", -end:"$|;",illegal:/=/,contains:[a.inherit(a.TITLE_MODE,{ -begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|!)?"}),{begin:"<\\s*",contains:[{ -begin:"("+a.IDENT_RE+"::)?"+a.IDENT_RE,relevance:0}]}].concat(c)},{ -className:"function",begin:n(/def\s+/,e(i+"\\s*(\\(|;|$)")),relevance:0, -keywords:"def",end:"$|;",contains:[a.inherit(a.TITLE_MODE,{begin:i -}),o].concat(c)},{begin:a.IDENT_RE+"::"},{className:"symbol", -begin:a.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol", -begin:":(?!\\s)",contains:[g,{begin:i}],relevance:0},l,{className:"variable", -begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{ -className:"params",begin:/\|/,end:/\|/,relevance:0,keywords:s},{ -begin:"("+a.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{ -className:"regexp",contains:[a.BACKSLASH_ESCAPE,t],illegal:/\n/,variants:[{ -begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(", -end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}] -}].concat(b,c),relevance:0}].concat(b,c);t.contains=_,o.contains=_;const E=[{ -begin:/^\s*=>/,starts:{end:"$",contains:_}},{className:"meta", -begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])", -starts:{end:"$",contains:_}}];return c.unshift(b),{name:"Ruby", -aliases:["rb","gemspec","podspec","thor","irb"],keywords:s,illegal:/\/\*/, -contains:[a.SHEBANG({binary:"ruby"})].concat(E).concat(c).concat(_)}}})());hljs.registerLanguage("yaml",(()=>{"use strict";return e=>{ -const n="true false yes no null",a="[\\w#;/?:@&=+$,.~*'()[\\]]+",s={ -className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/ -},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable", -variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(s,{ -variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={ -end:",",endsWithParent:!0,excludeEnd:!0,keywords:n,relevance:0},t={begin:/\{/, -end:/\}/,contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]", -contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",variants:[{ -begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{ -begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$", -relevance:10},{className:"string", -begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{ -begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0, -relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type", -begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a -},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta", -begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)", -relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{ -className:"number", -begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b" -},{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},t,g,s],c=[...b] -;return c.pop(),c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0, -aliases:["yml"],contains:b}}})());hljs.registerLanguage("css",(()=>{"use strict" -;const e=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","p","q","quote","samp","section","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],t=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"],i=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"],o=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"],r=["align-content","align-items","align-self","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","auto","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","clip-path","color","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","cursor","direction","display","empty-cells","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-variant","font-variant-ligatures","font-variation-settings","font-weight","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inherit","initial","justify-content","left","letter-spacing","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","mask","max-height","max-width","min-height","min-width","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","perspective","perspective-origin","pointer-events","position","quotes","resize","right","src","tab-size","table-layout","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-indent","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","white-space","widows","width","word-break","word-spacing","word-wrap","z-index"].reverse() -;return n=>{const a=(e=>({IMPORTANT:{scope:"meta",begin:"!important"},HEXCOLOR:{ -scope:"number",begin:"#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})"}, -ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", -contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{ -scope:"number", -begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", -relevance:0}}))(n),l=[n.APOS_STRING_MODE,n.QUOTE_STRING_MODE];return{name:"CSS", -case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"}, -classNameAliases:{keyframePosition:"selector-tag"}, -contains:[n.C_BLOCK_COMMENT_MODE,{begin:/-(webkit|moz|ms|o)-(?=[a-z])/ -},a.CSS_NUMBER_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0 -},{className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0 -},a.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{ -begin:":("+i.join("|")+")"},{begin:"::("+o.join("|")+")"}]},{ -className:"attribute",begin:"\\b("+r.join("|")+")\\b"},{begin:":",end:"[;}]", -contains:[a.HEXCOLOR,a.IMPORTANT,a.CSS_NUMBER_MODE,...l,{ -begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri" -},contains:[{className:"string",begin:/[^)]/,endsWithParent:!0,excludeEnd:!0}] -},{className:"built_in",begin:/[\w-]+(?=\()/}]},{ -begin:(s=/@/,((...e)=>e.map((e=>(e=>e?"string"==typeof e?e:e.source:null)(e))).join(""))("(?=",s,")")), -end:"[{;]",relevance:0,illegal:/:/,contains:[{className:"keyword", -begin:/@-?\w[\w]*(-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0, -relevance:0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only", -attribute:t.join(" ")},contains:[{begin:/[a-z-]+(?=:)/,className:"attribute" -},...l,a.CSS_NUMBER_MODE]}]},{className:"selector-tag", -begin:"\\b("+e.join("|")+")\\b"}]};var s}})());hljs.registerLanguage("bash",(()=>{"use strict";function e(...e){ -return e.map((e=>{return(s=e)?"string"==typeof s?s:s.source:null;var s -})).join("")}return s=>{const n={},t={begin:/\$\{/,end:/\}/,contains:["self",{ -begin:/:-/,contains:[n]}]};Object.assign(n,{className:"variable",variants:[{ -begin:e(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},t]});const a={ -className:"subst",begin:/\$\(/,end:/\)/,contains:[s.BACKSLASH_ESCAPE]},i={ -begin:/<<-?\s*(?=\w+)/,starts:{contains:[s.END_SAME_AS_BEGIN({begin:/(\w+)/, -end:/(\w+)/,className:"string"})]}},c={className:"string",begin:/"/,end:/"/, -contains:[s.BACKSLASH_ESCAPE,n,a]};a.contains.push(c);const o={begin:/\$\(\(/, -end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},s.NUMBER_MODE,n] -},r=s.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 -}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, -contains:[s.inherit(s.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ -name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z._-]+\b/, -keyword:["if","then","else","elif","fi","for","while","in","do","done","case","esac","function"], -literal:["true","false"], -built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp" -},contains:[r,s.SHEBANG(),l,o,s.HASH_COMMENT_MODE,i,c,{className:"",begin:/\\"/ -},{className:"string",begin:/'/,end:/'/},n]}}})());hljs.registerLanguage("xml",(()=>{"use strict";function e(e){ -return e?"string"==typeof e?e:e.source:null}function n(e){return a("(?=",e,")")} -function a(...n){return n.map((n=>e(n))).join("")}function s(...n){ -return"("+((e=>{const n=e[e.length-1] -;return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{} -})(n).capture?"":"?:")+n.map((n=>e(n))).join("|")+")"}return e=>{ -const t=a(/[A-Z_]/,a("(?:",/[A-Z0-9_.-]*:/,")?"),/[A-Z0-9_.-]*/),i={ -className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},c={begin:/\s/, -contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] -},r=e.inherit(c,{begin:/\(/,end:/\)/}),l=e.inherit(e.APOS_STRING_MODE,{ -className:"string"}),g=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),m={ -endsWithParent:!0,illegal:/`]+/}]}]}]};return{ -name:"HTML, XML", -aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], -case_insensitive:!0,contains:[{className:"meta",begin://, -relevance:10,contains:[c,g,l,r,{begin:/\[/,end:/\]/,contains:[{className:"meta", -begin://,contains:[c,r,g,l]}]}]},e.COMMENT(//,{ -relevance:10}),{begin://,relevance:10},i,{ -className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag", -begin:/)/,end:/>/,keywords:{name:"style"},contains:[m],starts:{ -end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", -begin:/)/,end:/>/,keywords:{name:"script"},contains:[m],starts:{ -end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ -className:"tag",begin:/<>|<\/>/},{className:"tag", -begin:a(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name", -begin:t,relevance:0,starts:m}]},{className:"tag",begin:a(/<\//,n(a(t,/>/))), -contains:[{className:"name",begin:t,relevance:0},{begin:/>/,relevance:0, -endsParent:!0}]}]}}})());hljs.registerLanguage("markdown",(()=>{"use strict";function n(...n){ -return n.map((n=>{return(e=n)?"string"==typeof e?e:e.source:null;var e -})).join("")}return e=>{const a={begin:/<\/?[A-Za-z_]/,end:">", -subLanguage:"xml",relevance:0},i={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0 -},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, -relevance:2},{begin:n(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), -relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ -begin:/\[.+?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{ -className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, -returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", -excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", -end:"\\]",excludeBegin:!0,excludeEnd:!0}]},s={className:"strong",contains:[], -variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},c={ -className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{ -begin:/_(?!_)/,end:/_/,relevance:0}]};s.contains.push(c),c.contains.push(s) -;let t=[a,i] -;return s.contains=s.contains.concat(t),c.contains=c.contains.concat(t), -t=t.concat(s,c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ -className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:t},{ -begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", -contains:t}]}]},a,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", -end:"\\s+",excludeEnd:!0},s,c,{className:"quote",begin:"^>\\s+",contains:t, -end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ -begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ -begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", -contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ -begin:"^[-\\*]{3,}",end:"$"},i,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ -className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ -className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})());hljs.registerLanguage("plaintext",(()=>{"use strict";return t=>({ -name:"Plain text",aliases:["text","txt"],disableAutodetect:!0})})());hljs.registerLanguage("objectivec",(()=>{"use strict";return e=>{ -const n=/[a-zA-Z@][a-zA-Z0-9_]*/,_={$pattern:n, -keyword:["@interface","@class","@protocol","@implementation"]};return{ -name:"Objective-C",aliases:["mm","objc","obj-c","obj-c++","objective-c++"], -keywords:{$pattern:n, -keyword:["int","float","while","char","export","sizeof","typedef","const","struct","for","union","unsigned","long","volatile","static","bool","mutable","if","do","return","goto","void","enum","else","break","extern","asm","case","short","default","double","register","explicit","signed","typename","this","switch","continue","wchar_t","inline","readonly","assign","readwrite","self","@synchronized","id","typeof","nonatomic","super","unichar","IBOutlet","IBAction","strong","weak","copy","in","out","inout","bycopy","byref","oneway","__strong","__weak","__block","__autoreleasing","@private","@protected","@public","@try","@property","@end","@throw","@catch","@finally","@autoreleasepool","@synthesize","@dynamic","@selector","@optional","@required","@encode","@package","@import","@defs","@compatibility_alias","__bridge","__bridge_transfer","__bridge_retained","__bridge_retain","__covariant","__contravariant","__kindof","_Nonnull","_Nullable","_Null_unspecified","__FUNCTION__","__PRETTY_FUNCTION__","__attribute__","getter","setter","retain","unsafe_unretained","nonnull","nullable","null_unspecified","null_resettable","class","instancetype","NS_DESIGNATED_INITIALIZER","NS_UNAVAILABLE","NS_REQUIRES_SUPER","NS_RETURNS_INNER_POINTER","NS_INLINE","NS_AVAILABLE","NS_DEPRECATED","NS_ENUM","NS_OPTIONS","NS_SWIFT_UNAVAILABLE","NS_ASSUME_NONNULL_BEGIN","NS_ASSUME_NONNULL_END","NS_REFINED_FOR_SWIFT","NS_SWIFT_NAME","NS_SWIFT_NOTHROW","NS_DURING","NS_HANDLER","NS_ENDHANDLER","NS_VALUERETURN","NS_VOIDRETURN"], -literal:["false","true","FALSE","TRUE","nil","YES","NO","NULL"], -built_in:["BOOL","dispatch_once_t","dispatch_queue_t","dispatch_sync","dispatch_async","dispatch_once"] -},illegal:"/,end:/$/,illegal:"\\n" -},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"class", -begin:"("+_.keyword.join("|")+")\\b",end:/(\{|$)/,excludeEnd:!0,keywords:_, -contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"\\."+e.UNDERSCORE_IDENT_RE, -relevance:0}]}}})());hljs.registerLanguage("lisp",(()=>{"use strict";return e=>{ -var n="[a-zA-Z_\\-+\\*\\/<=>&#][a-zA-Z0-9_\\-+*\\/<=>&#!]*",a="\\|[^]*?\\|",i="(-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|-)?\\d+)?",s={ -className:"literal",begin:"\\b(t{1}|nil)\\b"},l={className:"number",variants:[{ -begin:i,relevance:0},{begin:"#(b|B)[0-1]+(/[0-1]+)?"},{ -begin:"#(o|O)[0-7]+(/[0-7]+)?"},{begin:"#(x|X)[0-9a-fA-F]+(/[0-9a-fA-F]+)?"},{ -begin:"#(c|C)\\("+i+" +"+i,end:"\\)"}]},b=e.inherit(e.QUOTE_STRING_MODE,{ -illegal:null}),g=e.COMMENT(";","$",{relevance:0}),r={begin:"\\*",end:"\\*"},t={ -className:"symbol",begin:"[:&]"+n},c={begin:n,relevance:0},d={begin:a},o={ -contains:[l,b,r,t,{begin:"\\(",end:"\\)",contains:["self",s,b,l,c]},c], -variants:[{begin:"['`]\\(",end:"\\)"},{begin:"\\(quote ",end:"\\)",keywords:{ -name:"quote"}},{begin:"'"+a}]},v={variants:[{begin:"'"+n},{ -begin:"#'"+n+"(::"+n+")*"}]},m={begin:"\\(\\s*",end:"\\)"},u={endsWithParent:!0, -relevance:0};return m.contains=[{className:"name",variants:[{begin:n,relevance:0 -},{begin:a}]},u],u.contains=[o,v,m,s,l,b,g,r,t,d,c],{name:"Lisp",illegal:/\S/, -contains:[l,e.SHEBANG(),s,b,g,o,v,m,c]}}})());hljs.registerLanguage("json",(()=>{"use strict";return e=>({name:"JSON", -contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01 -},{match:/[{}[\],:]/,className:"punctuation",relevance:0},e.QUOTE_STRING_MODE,{ -beginKeywords:"true false null" -},e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:"\\S"}) -})()); \ No newline at end of file diff --git a/static/highlight/styles/atom-one-dark.min.css b/static/highlight/styles/atom-one-dark.min.css deleted file mode 100644 index 5344ee38..00000000 --- a/static/highlight/styles/atom-one-dark.min.css +++ /dev/null @@ -1 +0,0 @@ -pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-comment,.hljs-quote{color:#5c6370;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline} \ No newline at end of file From bc249a027b19ac0a7432f4c7aaeaa62958d93d98 Mon Sep 17 00:00:00 2001 From: Alexander Artemenko Date: Fri, 3 Sep 2021 17:24:17 +0300 Subject: [PATCH 05/11] Use nonbroken Ultralisp version 20210903140500. --- qlfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qlfile.lock b/qlfile.lock index 9151d5f9..d12a5e46 100644 --- a/qlfile.lock +++ b/qlfile.lock @@ -5,4 +5,4 @@ ("ultralisp" . (:class qlot/source/dist:source-dist :initargs (:distribution "http://dist.ultralisp.org" :%version :latest) - :version "20210901054000")) + :version "20210903140500")) From 8499f5d42466a66295507241b10d8f255ed14b08 Mon Sep 17 00:00:00 2001 From: Alexander Artemenko Date: Fri, 3 Sep 2021 17:39:48 +0300 Subject: [PATCH 06/11] Fixed deps. --- src/highlight.lisp | 21 +++++++++++++-------- src/themes/default.lisp | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/highlight.lisp b/src/highlight.lisp index 53b591a7..b12a44da 100644 --- a/src/highlight.lisp +++ b/src/highlight.lisp @@ -3,14 +3,19 @@ (:import-from #:dexador) (:import-from #:log4cl) (:import-from #:alexandria - #:when-let) + #:when-let + #:write-string-into-file + #:write-byte-vector-into-file + #:read-file-into-string) (:import-from #:cl-cookie #:cookie-value #:cookie-name #:make-cookie-jar #:cookie-jar-cookies) (:import-from #:tmpdir - #:with-tmpdir)) + #:with-tmpdir) + (:import-from #:trivial-extract + #:extract-zip)) (in-package 40ants-doc/highlight) @@ -246,7 +251,7 @@ (cond ((and (probe-file metadata-path) - (string= (alexandria:read-file-into-string metadata-path) + (string= (read-file-into-string metadata-path) metadata)) (log:info "METADATA file lists same languages and theme. Skipping download of Highlight.js")) (t @@ -274,9 +279,9 @@ (ensure-directories-exist path) (ensure-directories-exist to) - (alexandria:write-byte-vector-into-file response path - :if-exists :supersede) - (trivial-extract:extract-zip path) + (write-byte-vector-into-file response path + :if-exists :supersede) + (extract-zip path) (uiop:copy-file (uiop:merge-pathnames* "highlight.min.js" tmpdir) (uiop:merge-pathnames* "highlight.min.js" to)) @@ -290,6 +295,6 @@ (uiop:copy-file theme-path (uiop:merge-pathnames* "highlight.min.css" to))) - (alexandria:write-string-into-file metadata metadata-path - :if-exists :supersede)))))) + (write-string-into-file metadata metadata-path + :if-exists :supersede)))))) (values)) diff --git a/src/themes/default.lisp b/src/themes/default.lisp index e58aa723..d1593c18 100644 --- a/src/themes/default.lisp +++ b/src/themes/default.lisp @@ -7,6 +7,7 @@ #:with-html) (:import-from #:40ants-doc/utils #:make-relative-path) + (:import-from #:40ants-doc/rewrite) (:export #:default-theme)) (in-package 40ants-doc/themes/default) From d98d21859512103e604eecd6e6ddd7816a7f5391 Mon Sep 17 00:00:00 2001 From: Alexander Artemenko Date: Fri, 3 Sep 2021 17:49:40 +0300 Subject: [PATCH 07/11] Updated test baseline. --- test/data/baseline/highlight.min.js | 218 ++++++++---------- .../data/baseline/other/test-other/index.html | 26 +-- test/data/baseline/search/index.html | 24 +- test/data/baseline/test/index.html | 26 +-- test/data/baseline/theme.css | 63 ++--- test/data/baseline/toc.js | 4 +- 6 files changed, 165 insertions(+), 196 deletions(-) diff --git a/test/data/baseline/highlight.min.js b/test/data/baseline/highlight.min.js index 0edc9a13..b536e347 100644 --- a/test/data/baseline/highlight.min.js +++ b/test/data/baseline/highlight.min.js @@ -296,7 +296,89 @@ e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),s.push(e)} })({}),Y=Object.freeze({__proto__:null});const Q=J ;for(const e of Object.keys(Y)){const t=e.replace("grmr_","") ;Q.registerLanguage(t,Y[e])}return Q}() -;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);hljs.registerLanguage("ruby",(()=>{"use strict";function e(e){ +;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);hljs.registerLanguage("json",(()=>{"use strict";return e=>({name:"JSON", +contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01 +},{match:/[{}[\],:]/,className:"punctuation",relevance:0},e.QUOTE_STRING_MODE,{ +beginKeywords:"true false null" +},e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:"\\S"}) +})());hljs.registerLanguage("bash",(()=>{"use strict";function e(...e){ +return e.map((e=>{return(s=e)?"string"==typeof s?s:s.source:null;var s +})).join("")}return s=>{const n={},t={begin:/\$\{/,end:/\}/,contains:["self",{ +begin:/:-/,contains:[n]}]};Object.assign(n,{className:"variable",variants:[{ +begin:e(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},t]});const a={ +className:"subst",begin:/\$\(/,end:/\)/,contains:[s.BACKSLASH_ESCAPE]},i={ +begin:/<<-?\s*(?=\w+)/,starts:{contains:[s.END_SAME_AS_BEGIN({begin:/(\w+)/, +end:/(\w+)/,className:"string"})]}},c={className:"string",begin:/"/,end:/"/, +contains:[s.BACKSLASH_ESCAPE,n,a]};a.contains.push(c);const o={begin:/\$\(\(/, +end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},s.NUMBER_MODE,n] +},r=s.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 +}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, +contains:[s.inherit(s.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ +name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z._-]+\b/, +keyword:["if","then","else","elif","fi","for","while","in","do","done","case","esac","function"], +literal:["true","false"], +built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp" +},contains:[r,s.SHEBANG(),l,o,s.HASH_COMMENT_MODE,i,c,{className:"",begin:/\\"/ +},{className:"string",begin:/'/,end:/'/},n]}}})());hljs.registerLanguage("xml",(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function n(e){return a("(?=",e,")")} +function a(...n){return n.map((n=>e(n))).join("")}function s(...n){ +return"("+((e=>{const n=e[e.length-1] +;return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{} +})(n).capture?"":"?:")+n.map((n=>e(n))).join("|")+")"}return e=>{ +const t=a(/[A-Z_]/,a("(?:",/[A-Z0-9_.-]*:/,")?"),/[A-Z0-9_.-]*/),i={ +className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},c={begin:/\s/, +contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] +},r=e.inherit(c,{begin:/\(/,end:/\)/}),l=e.inherit(e.APOS_STRING_MODE,{ +className:"string"}),g=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),m={ +endsWithParent:!0,illegal:/`]+/}]}]}]};return{ +name:"HTML, XML", +aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], +case_insensitive:!0,contains:[{className:"meta",begin://, +relevance:10,contains:[c,g,l,r,{begin:/\[/,end:/\]/,contains:[{className:"meta", +begin://,contains:[c,r,g,l]}]}]},e.COMMENT(//,{ +relevance:10}),{begin://,relevance:10},i,{ +className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"style"},contains:[m],starts:{ +end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"script"},contains:[m],starts:{ +end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ +className:"tag",begin:/<>|<\/>/},{className:"tag", +begin:a(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name", +begin:t,relevance:0,starts:m}]},{className:"tag",begin:a(/<\//,n(a(t,/>/))), +contains:[{className:"name",begin:t,relevance:0},{begin:/>/,relevance:0, +endsParent:!0}]}]}}})());hljs.registerLanguage("markdown",(()=>{"use strict";function n(...n){ +return n.map((n=>{return(e=n)?"string"==typeof e?e:e.source:null;var e +})).join("")}return e=>{const a={begin:/<\/?[A-Za-z_]/,end:">", +subLanguage:"xml",relevance:0},i={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0 +},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, +relevance:2},{begin:n(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), +relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ +begin:/\[.+?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{ +className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, +returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", +excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", +end:"\\]",excludeBegin:!0,excludeEnd:!0}]},s={className:"strong",contains:[], +variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},c={ +className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{ +begin:/_(?!_)/,end:/_/,relevance:0}]};s.contains.push(c),c.contains.push(s) +;let t=[a,i] +;return s.contains=s.contains.concat(t),c.contains=c.contains.concat(t), +t=t.concat(s,c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ +className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:t},{ +begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", +contains:t}]}]},a,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", +end:"\\s+",excludeEnd:!0},s,c,{className:"quote",begin:"^>\\s+",contains:t, +end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ +begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ +begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", +contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ +begin:"^[-\\*]{3,}",end:"$"},i,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ +className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ +className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})());hljs.registerLanguage("plaintext",(()=>{"use strict";return t=>({ +name:"Plain text",aliases:["text","txt"],disableAutodetect:!0})})());hljs.registerLanguage("ruby",(()=>{"use strict";function e(e){ return n("(?=",e,")")}function n(...e){return e.map((e=>{ return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return a=>{ const i="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",s={ @@ -366,7 +448,21 @@ className:"number", begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b" },{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},t,g,s],c=[...b] ;return c.pop(),c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0, -aliases:["yml"],contains:b}}})());hljs.registerLanguage("css",(()=>{"use strict" +aliases:["yml"],contains:b}}})());hljs.registerLanguage("lisp",(()=>{"use strict";return e=>{ +var n="[a-zA-Z_\\-+\\*\\/<=>&#][a-zA-Z0-9_\\-+*\\/<=>&#!]*",a="\\|[^]*?\\|",i="(-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|-)?\\d+)?",s={ +className:"literal",begin:"\\b(t{1}|nil)\\b"},l={className:"number",variants:[{ +begin:i,relevance:0},{begin:"#(b|B)[0-1]+(/[0-1]+)?"},{ +begin:"#(o|O)[0-7]+(/[0-7]+)?"},{begin:"#(x|X)[0-9a-fA-F]+(/[0-9a-fA-F]+)?"},{ +begin:"#(c|C)\\("+i+" +"+i,end:"\\)"}]},b=e.inherit(e.QUOTE_STRING_MODE,{ +illegal:null}),g=e.COMMENT(";","$",{relevance:0}),r={begin:"\\*",end:"\\*"},t={ +className:"symbol",begin:"[:&]"+n},c={begin:n,relevance:0},d={begin:a},o={ +contains:[l,b,r,t,{begin:"\\(",end:"\\)",contains:["self",s,b,l,c]},c], +variants:[{begin:"['`]\\(",end:"\\)"},{begin:"\\(quote ",end:"\\)",keywords:{ +name:"quote"}},{begin:"'"+a}]},v={variants:[{begin:"'"+n},{ +begin:"#'"+n+"(::"+n+")*"}]},m={begin:"\\(\\s*",end:"\\)"},u={endsWithParent:!0, +relevance:0};return m.contains=[{className:"name",variants:[{begin:n,relevance:0 +},{begin:a}]},u],u.contains=[o,v,m,s,l,b,g,r,t,d,c],{name:"Lisp",illegal:/\S/, +contains:[l,e.SHEBANG(),s,b,g,o,v,m,c]}}})());hljs.registerLanguage("css",(()=>{"use strict" ;const e=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","p","q","quote","samp","section","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],t=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"],i=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"],o=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"],r=["align-content","align-items","align-self","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","auto","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","clip-path","color","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","cursor","direction","display","empty-cells","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-variant","font-variant-ligatures","font-variation-settings","font-weight","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inherit","initial","justify-content","left","letter-spacing","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","mask","max-height","max-width","min-height","min-width","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","perspective","perspective-origin","pointer-events","position","quotes","resize","right","src","tab-size","table-layout","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-indent","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","white-space","widows","width","word-break","word-spacing","word-wrap","z-index"].reverse() ;return n=>{const a=(e=>({IMPORTANT:{scope:"meta",begin:"!important"},HEXCOLOR:{ scope:"number",begin:"#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})"}, @@ -393,120 +489,4 @@ begin:/@-?\w[\w]*(-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0, relevance:0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only", attribute:t.join(" ")},contains:[{begin:/[a-z-]+(?=:)/,className:"attribute" },...l,a.CSS_NUMBER_MODE]}]},{className:"selector-tag", -begin:"\\b("+e.join("|")+")\\b"}]};var s}})());hljs.registerLanguage("bash",(()=>{"use strict";function e(...e){ -return e.map((e=>{return(s=e)?"string"==typeof s?s:s.source:null;var s -})).join("")}return s=>{const n={},t={begin:/\$\{/,end:/\}/,contains:["self",{ -begin:/:-/,contains:[n]}]};Object.assign(n,{className:"variable",variants:[{ -begin:e(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},t]});const a={ -className:"subst",begin:/\$\(/,end:/\)/,contains:[s.BACKSLASH_ESCAPE]},i={ -begin:/<<-?\s*(?=\w+)/,starts:{contains:[s.END_SAME_AS_BEGIN({begin:/(\w+)/, -end:/(\w+)/,className:"string"})]}},c={className:"string",begin:/"/,end:/"/, -contains:[s.BACKSLASH_ESCAPE,n,a]};a.contains.push(c);const o={begin:/\$\(\(/, -end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},s.NUMBER_MODE,n] -},r=s.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 -}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, -contains:[s.inherit(s.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ -name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z._-]+\b/, -keyword:["if","then","else","elif","fi","for","while","in","do","done","case","esac","function"], -literal:["true","false"], -built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp" -},contains:[r,s.SHEBANG(),l,o,s.HASH_COMMENT_MODE,i,c,{className:"",begin:/\\"/ -},{className:"string",begin:/'/,end:/'/},n]}}})());hljs.registerLanguage("xml",(()=>{"use strict";function e(e){ -return e?"string"==typeof e?e:e.source:null}function n(e){return a("(?=",e,")")} -function a(...n){return n.map((n=>e(n))).join("")}function s(...n){ -return"("+((e=>{const n=e[e.length-1] -;return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{} -})(n).capture?"":"?:")+n.map((n=>e(n))).join("|")+")"}return e=>{ -const t=a(/[A-Z_]/,a("(?:",/[A-Z0-9_.-]*:/,")?"),/[A-Z0-9_.-]*/),i={ -className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},c={begin:/\s/, -contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] -},r=e.inherit(c,{begin:/\(/,end:/\)/}),l=e.inherit(e.APOS_STRING_MODE,{ -className:"string"}),g=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),m={ -endsWithParent:!0,illegal:/`]+/}]}]}]};return{ -name:"HTML, XML", -aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], -case_insensitive:!0,contains:[{className:"meta",begin://, -relevance:10,contains:[c,g,l,r,{begin:/\[/,end:/\]/,contains:[{className:"meta", -begin://,contains:[c,r,g,l]}]}]},e.COMMENT(//,{ -relevance:10}),{begin://,relevance:10},i,{ -className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag", -begin:/)/,end:/>/,keywords:{name:"style"},contains:[m],starts:{ -end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", -begin:/)/,end:/>/,keywords:{name:"script"},contains:[m],starts:{ -end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ -className:"tag",begin:/<>|<\/>/},{className:"tag", -begin:a(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name", -begin:t,relevance:0,starts:m}]},{className:"tag",begin:a(/<\//,n(a(t,/>/))), -contains:[{className:"name",begin:t,relevance:0},{begin:/>/,relevance:0, -endsParent:!0}]}]}}})());hljs.registerLanguage("markdown",(()=>{"use strict";function n(...n){ -return n.map((n=>{return(e=n)?"string"==typeof e?e:e.source:null;var e -})).join("")}return e=>{const a={begin:/<\/?[A-Za-z_]/,end:">", -subLanguage:"xml",relevance:0},i={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0 -},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, -relevance:2},{begin:n(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), -relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ -begin:/\[.+?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{ -className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, -returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", -excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", -end:"\\]",excludeBegin:!0,excludeEnd:!0}]},s={className:"strong",contains:[], -variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},c={ -className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{ -begin:/_(?!_)/,end:/_/,relevance:0}]};s.contains.push(c),c.contains.push(s) -;let t=[a,i] -;return s.contains=s.contains.concat(t),c.contains=c.contains.concat(t), -t=t.concat(s,c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ -className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:t},{ -begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", -contains:t}]}]},a,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", -end:"\\s+",excludeEnd:!0},s,c,{className:"quote",begin:"^>\\s+",contains:t, -end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ -begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ -begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", -contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ -begin:"^[-\\*]{3,}",end:"$"},i,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ -className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ -className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})());hljs.registerLanguage("plaintext",(()=>{"use strict";return t=>({ -name:"Plain text",aliases:["text","txt"],disableAutodetect:!0})})());hljs.registerLanguage("objectivec",(()=>{"use strict";return e=>{ -const n=/[a-zA-Z@][a-zA-Z0-9_]*/,_={$pattern:n, -keyword:["@interface","@class","@protocol","@implementation"]};return{ -name:"Objective-C",aliases:["mm","objc","obj-c","obj-c++","objective-c++"], -keywords:{$pattern:n, -keyword:["int","float","while","char","export","sizeof","typedef","const","struct","for","union","unsigned","long","volatile","static","bool","mutable","if","do","return","goto","void","enum","else","break","extern","asm","case","short","default","double","register","explicit","signed","typename","this","switch","continue","wchar_t","inline","readonly","assign","readwrite","self","@synchronized","id","typeof","nonatomic","super","unichar","IBOutlet","IBAction","strong","weak","copy","in","out","inout","bycopy","byref","oneway","__strong","__weak","__block","__autoreleasing","@private","@protected","@public","@try","@property","@end","@throw","@catch","@finally","@autoreleasepool","@synthesize","@dynamic","@selector","@optional","@required","@encode","@package","@import","@defs","@compatibility_alias","__bridge","__bridge_transfer","__bridge_retained","__bridge_retain","__covariant","__contravariant","__kindof","_Nonnull","_Nullable","_Null_unspecified","__FUNCTION__","__PRETTY_FUNCTION__","__attribute__","getter","setter","retain","unsafe_unretained","nonnull","nullable","null_unspecified","null_resettable","class","instancetype","NS_DESIGNATED_INITIALIZER","NS_UNAVAILABLE","NS_REQUIRES_SUPER","NS_RETURNS_INNER_POINTER","NS_INLINE","NS_AVAILABLE","NS_DEPRECATED","NS_ENUM","NS_OPTIONS","NS_SWIFT_UNAVAILABLE","NS_ASSUME_NONNULL_BEGIN","NS_ASSUME_NONNULL_END","NS_REFINED_FOR_SWIFT","NS_SWIFT_NAME","NS_SWIFT_NOTHROW","NS_DURING","NS_HANDLER","NS_ENDHANDLER","NS_VALUERETURN","NS_VOIDRETURN"], -literal:["false","true","FALSE","TRUE","nil","YES","NO","NULL"], -built_in:["BOOL","dispatch_once_t","dispatch_queue_t","dispatch_sync","dispatch_async","dispatch_once"] -},illegal:"/,end:/$/,illegal:"\\n" -},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"class", -begin:"("+_.keyword.join("|")+")\\b",end:/(\{|$)/,excludeEnd:!0,keywords:_, -contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"\\."+e.UNDERSCORE_IDENT_RE, -relevance:0}]}}})());hljs.registerLanguage("lisp",(()=>{"use strict";return e=>{ -var n="[a-zA-Z_\\-+\\*\\/<=>&#][a-zA-Z0-9_\\-+*\\/<=>&#!]*",a="\\|[^]*?\\|",i="(-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|-)?\\d+)?",s={ -className:"literal",begin:"\\b(t{1}|nil)\\b"},l={className:"number",variants:[{ -begin:i,relevance:0},{begin:"#(b|B)[0-1]+(/[0-1]+)?"},{ -begin:"#(o|O)[0-7]+(/[0-7]+)?"},{begin:"#(x|X)[0-9a-fA-F]+(/[0-9a-fA-F]+)?"},{ -begin:"#(c|C)\\("+i+" +"+i,end:"\\)"}]},b=e.inherit(e.QUOTE_STRING_MODE,{ -illegal:null}),g=e.COMMENT(";","$",{relevance:0}),r={begin:"\\*",end:"\\*"},t={ -className:"symbol",begin:"[:&]"+n},c={begin:n,relevance:0},d={begin:a},o={ -contains:[l,b,r,t,{begin:"\\(",end:"\\)",contains:["self",s,b,l,c]},c], -variants:[{begin:"['`]\\(",end:"\\)"},{begin:"\\(quote ",end:"\\)",keywords:{ -name:"quote"}},{begin:"'"+a}]},v={variants:[{begin:"'"+n},{ -begin:"#'"+n+"(::"+n+")*"}]},m={begin:"\\(\\s*",end:"\\)"},u={endsWithParent:!0, -relevance:0};return m.contains=[{className:"name",variants:[{begin:n,relevance:0 -},{begin:a}]},u],u.contains=[o,v,m,s,l,b,g,r,t,d,c],{name:"Lisp",illegal:/\S/, -contains:[l,e.SHEBANG(),s,b,g,o,v,m,c]}}})());hljs.registerLanguage("json",(()=>{"use strict";return e=>({name:"JSON", -contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01 -},{match:/[{}[\],:]/,className:"punctuation",relevance:0},e.QUOTE_STRING_MODE,{ -beginKeywords:"true false null" -},e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:"\\S"}) -})()); \ No newline at end of file +begin:"\\b("+e.join("|")+")\\b"}]};var s}})()); \ No newline at end of file diff --git a/test/data/baseline/other/test-other/index.html b/test/data/baseline/other/test-other/index.html index 564dc52f..e1afa7b6 100644 --- a/test/data/baseline/other/test-other/index.html +++ b/test/data/baseline/other/test-other/index.html @@ -1,8 +1,7 @@ - - + Test other title @@ -25,20 +24,17 @@ src=https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js> -
-
- - - - - -