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")) diff --git a/src/builder.lisp b/src/builder.lisp index 4466be37..2477ed68 100644 --- a/src/builder.lisp +++ b/src/builder.lisp @@ -5,7 +5,8 @@ (:import-from #:3bmd-code-blocks) (:import-from #:named-readtables) (:import-from #:pythonic-string-reader) - (:import-from #:40ants-doc/builder/vars) + (:import-from #:40ants-doc/builder/vars + #:*current-page*) (:import-from #:40ants-doc/page #:page-base-dir #:page-format) @@ -22,6 +23,7 @@ (:import-from #:40ants-doc/search) (:import-from #:40ants-doc/commondoc/transcribe) (:import-from #:40ants-doc/changelog) + (:import-from #:40ants-doc/commondoc/image) (:export #:*document-html-top-blocks-of-links* #:*document-html-bottom-blocks-of-links* @@ -106,7 +108,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 @@ -121,7 +125,7 @@ See docs on RENDER-TO-FILES function to learn about meaning of BASE-DIR, BASE-URL, SOURCE-URI-FN, WARN-ON-UNDOCUMENTED-PACKAGES, CLEAN-URLS, - and DOWNCASE-UPPERCASE-CODE arguments. + DOWNCASE-UPPERCASE-CODE, THEME, HIGHLIGHT-LANGUAGES and HIGHLIGHT-THEME arguments. Example usage: @@ -170,6 +174,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 @@ -189,7 +195,8 @@ (document (if 40ants-doc/link:*document-link-code* (40ants-doc/commondoc/page::replace-xrefs document references :base-url base-url) - document))) + document)) + (document (40ants-doc/commondoc/image::replace-images document))) document)) @@ -214,14 +221,16 @@ stream)))))) -(defun render-to-files (sections &key (theme '40ants-doc/themes/default::default-theme) +(defun render-to-files (sections &key (theme '40ants-doc/themes/default:default-theme) (base-dir #P"./") (base-url nil) (source-uri-fn 40ants-doc/reference-api:*source-uri-fn*) (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. @@ -241,7 +250,20 @@ markdown files together with HTML. If DOWNCASE-UPPERCASE-CODE is true, then all references to symbols will be - downcased." + downcased. + + THEME argument should be a theme class name. By default it is + 40ANTS-DOC/THEMES/DEFAULT:DEFAULT-THEME. See 40ANTS-DOC/THEMES/DEFAULT::@DEFINING-A-THEME + to learn how to define themes. + + HIGHLIGHT-LANGUAGES and HIGHLIGHT-THEME arguments allow to redefine theme's + settings for Highlight.js. Languages should be a list of strings where each + item is a language name, [supported by Highlight.js][langs]. Theme should be a + name of a supported theme. You can preview different highlighting themes [here][themes] + + [langs]: https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md + [themes]: https://highlightjs.org/static/demo/ +" (setf format (40ants-doc/commondoc/format::ensure-format-class-name format)) @@ -253,106 +275,90 @@ (40ants-doc/commondoc/page::*warn-on-undocumented-packages* warn-on-undocumented-packages) (40ants-doc/rewrite::*clean-urls* clean-urls) (40ants-doc/reference-api:*source-uri-fn* source-uri-fn) - (40ants-doc/builder/vars::*downcase-uppercase-code* downcase-uppercase-code)) + (40ants-doc/builder/vars::*downcase-uppercase-code* downcase-uppercase-code) + (40ants-doc/builder/vars::*base-dir* base-dir)) (handler-bind ((warning (lambda (c) (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 *current-page* in page-documents + for full-filename = (make-full-filename *current-page*) + for format = (or + ;; Page may override global format setting + (page-format *current-page*) + 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) + *current-page* + stream) + (push full-filename output-paths))) + + (when (eql format + 'common-html:html) + (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" + :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/builder/vars.lisp b/src/builder/vars.lisp index b8a32b65..5ab40396 100644 --- a/src/builder/vars.lisp +++ b/src/builder/vars.lisp @@ -20,3 +20,15 @@ "If true, then the names of symbols recognized as code (including those found if *DOCUMENT-UPPERCASE-IS-CODE*) are downcased in the output if they only consist of uppercase characters.") + + +(defvar *base-dir*) +(setf (documentation '*base-dir* 'variable) + "This variable will be set to BASE-DIR argument value when calling RENDER-TO-FILES function. + + Some code might use it to place static files near HTML files.") + + +(defvar *current-page*) +(setf (documentation '*current-page* 'variable) + "This variable will be set to a current page when rendering documents inside RENDER-TO-FILES function.") diff --git a/src/commondoc/html.lisp b/src/commondoc/html.lisp index 3f0a28f5..b9a1bd84 100644 --- a/src/commondoc/html.lisp +++ b/src/commondoc/html.lisp @@ -2,12 +2,13 @@ (:use #:cl) (:import-from #:spinneret) (:import-from #:common-html.emitter) - (:export - #:with-html)) + (:export #:with-html)) (in-package 40ants-doc/commondoc/html) (defmacro with-html (&body body) + "Use this macro to render HTML inside generic-functions, + listed in the 40ANTS-DOC/THEMES/DEFAULT::@DEFINING-A-THEME section." `(let ((spinneret:*html* common-html.emitter::*output-stream*)) (spinneret:with-html ,@body))) diff --git a/src/commondoc/image.lisp b/src/commondoc/image.lisp new file mode 100644 index 00000000..2f52a8ee --- /dev/null +++ b/src/commondoc/image.lisp @@ -0,0 +1,102 @@ +(defpackage #:40ants-doc/commondoc/image + (:use #:cl) + (:import-from #:common-html.emitter + #:define-emitter) + (:import-from #:str) + (:import-from #:40ants-doc/commondoc/html + #:with-html) + (:import-from #:40ants-doc/commondoc/page + #:make-page-uri) + (:import-from #:40ants-doc/utils + #:make-relative-path) + (:import-from #:cl-ppcre + #:do-register-groups)) +(in-package 40ants-doc/commondoc/image) + +(defclass local-image (common-doc:image) + ((width :initform nil + :initarg :width + :reader width) + (height :initform nil + :initarg :height + :reader height))) + +(defun make-local-image (path &key width height) + (unless (probe-file path) + (error "Image file \"~A\" not found" + path)) + (make-instance 'local-image :source path + :width width + :height height)) + +(defun replace-images (document) + (flet ((replacer (node) + (typecase node + (common-doc:image + (let ((source (common-doc:source node))) + (if (or (str:starts-with-p "http:" source) + (str:starts-with-p "https:" source)) + node + (multiple-value-bind (source width height) + (extract-width-and-height source) + (make-local-image source + :width width + :height height))))) + (t node)))) + (40ants-doc/commondoc/mapper:map-nodes document #'replacer))) + +(defun extract-width-and-height (path) + "Returns 3 values, real path, width and height. Width and height might be NIL. + + For example, on \"blah.png{height=400,width=300}\" it will return: + + blah.png + 300 + 400" + + (let ((width nil) + (height nil)) + (do-register-groups (name value) ("[{,](.*?)=(.[^,}]*)" + path) + (cond + ((string-equal name "width") + (setf width + value)) + ((string-equal name "height") + (setf height + value)) + (t + (error "Parameter \"~A\" is not supported." + name)))) + + (values + (first (str:split "{" path)) + width + height))) + +(define-emitter (obj local-image) + "Emit a local-image and move referenced image into the HTML documentation folder." + (let* ((original-path (common-doc:source obj)) + (target-path (uiop:merge-pathnames* original-path + (uiop:merge-pathnames* #P"images/" + (uiop:ensure-directory-pathname + 40ants-doc/builder/vars::*base-dir*)))) + (page-uri (make-page-uri 40ants-doc/builder/vars::*current-page*)) + (new-source (make-relative-path page-uri + (format nil "images/~A" + original-path))) + (src (if common-html.emitter:*image-format-control* + (format nil common-html.emitter:*image-format-control* + new-source) + new-source)) + (description (common-doc:description obj))) + + (ensure-directories-exist target-path) + (uiop:copy-file original-path + target-path) + (with-html + (:img :src src + :alt description + :title description + :width (width obj) + :height (height obj))))) 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/core.lisp b/src/core.lisp index 7b10f543..0ecddaf9 100644 --- a/src/core.lisp +++ b/src/core.lisp @@ -223,16 +223,28 @@ (equal (ensure-list locative-1) (ensure-list locative-2))) + +(defun add-a-newline (text) + "Adds a new line text entries to make markdown parser correctly parse a header at the end of the text. + + Often you might end your text entry with a header like: + + ## API" + ;; and this function makes it work well + (concatenate 'string text " +")) + + (defun transform-entries (entries) (mapcar (lambda (entry) (typecase entry - (string entry) + (string (add-a-newline entry)) (symbol (let ((value (symbol-value entry))) (unless (typep value 'string) (error "~S value should be a string." entry)) - value)) + (add-a-newline value))) (t (entry-to-reference entry)))) entries)) diff --git a/src/doc.lisp b/src/doc.lisp index 70229799..a10f4d1b 100644 --- a/src/doc.lisp +++ b/src/doc.lisp @@ -20,6 +20,8 @@ (:import-from #:40ants-doc/source-api) (:import-from #:40ants-doc/changelog #:@changelog) + (:import-from #:40ants-doc/themes/default) + (:import-from #:40ants-doc/themes/docs) (:export #:@index #:@readme)) @@ -62,7 +64,7 @@ (defparameter *badges* " - +
@@ -554,6 +556,7 @@ See full list of changes in the 40ANTS-DOC/CHANGELOG::@CHANGELOG section. (defsection @extension-api (:title "Extension API") + (40ants-doc/themes/docs::@defining-a-theme section) (@locatives-and-references section) (@new-object-types section) (@reference-based-extensions section) diff --git a/src/full.lisp b/src/full.lisp index 34841a6a..1874dafe 100644 --- a/src/full.lisp +++ b/src/full.lisp @@ -28,5 +28,8 @@ (:import-from #:40ants-doc/locatives/stdout-of) (:import-from #:40ants-doc/github) (:import-from #:40ants-doc/commondoc/section) - (:import-from #:40ants-doc/object-package-impl)) + (:import-from #:40ants-doc/object-package-impl) + (:import-from #:40ants-doc/themes/default) + (:import-from #:40ants-doc/themes/light) + (:import-from #:40ants-doc/themes/dark)) (in-package 40ants-doc/full) diff --git a/src/highlight.lisp b/src/highlight.lisp new file mode 100644 index 00000000..b12a44da --- /dev/null +++ b/src/highlight.lisp @@ -0,0 +1,300 @@ +(defpackage #:40ants-doc/highlight + (:use #:cl) + (:import-from #:dexador) + (:import-from #:log4cl) + (:import-from #:alexandria + #: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) + (:import-from #:trivial-extract + #:extract-zip)) +(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= (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) + + (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)) + + (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))) + + (write-string-into-file metadata metadata-path + :if-exists :supersede)))))) + (values)) diff --git a/src/themes/api.lisp b/src/themes/api.lisp index 12fa7c7c..f2043476 100644 --- a/src/themes/api.lisp +++ b/src/themes/api.lisp @@ -1,9 +1,125 @@ (uiop:define-package #:40ants-doc/themes/api (:use #:cl) - (:export - #:render-css)) + (:import-from #:40ants-doc/highlight + #:download-highlight-js) + (: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 + #:render-page-header + #:render-page-footer + #:highlight-languages + #:highlight-theme)) (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 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: ") + (:method ((theme t)) + "magula")) (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-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.")) + +(defgeneric render-content (theme uri toc content-func) + (:documentation "Renders page's content. It can wrap content into HTML tags and should funcall CONTENT-FUNC without arguments.")) + +(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*) + (error "Please, use WITH-THEME macro around the call"))) + +(defun render-static (absolute-dir &key highlight-languages highlight-theme) + (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)) + + (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") + ("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))))) + +(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/dark.lisp b/src/themes/dark.lisp new file mode 100644 index 00000000..70df2295 --- /dev/null +++ b/src/themes/dark.lisp @@ -0,0 +1,49 @@ +(defpackage #:40ants-doc/themes/dark + (:use #:cl) + (:import-from #:40ants-doc/themes/default + #:default-theme) + (:import-from #:lass) + (:import-from #:40ants-doc/themes/api) + (:export #:dark-theme)) +(in-package 40ants-doc/themes/dark) + + +(defclass dark-theme (default-theme) + ()) + +(defmethod 40ants-doc/themes/api:render-css ((theme dark-theme)) + (let ((background "#333") + (font-color "#FFFEFB")) + (concatenate + 'string + (call-next-method) + + (lass:compile-and-write + `(body + :color ,font-color + :background ,background + + (.reference-object + :background "#7b2800") + + ((:or a code) + :color ,font-color) + + ((:or h1 h2 h3 h4 h5 h6) + :color ,font-color + :border-bottom none + :text-shadow "0.05em 0.05em 0.02em #000") + + (.sidebar + :background ,background + :box-shadow inset -3px 0 3px 0px "#777" + (.page-toc + (a + :color ,font-color)) + (.toc-active + :background ,font-color) + ((.toc-active > a) + :color ,background))))))) + +(defmethod 40ants-doc/themes/api:highlight-theme ((theme dark-theme)) + "atom-one-dark") diff --git a/src/themes/default.lisp b/src/themes/default.lisp index 63bbec97..7f9f7a1c 100644 --- a/src/themes/default.lisp +++ b/src/themes/default.lisp @@ -2,7 +2,13 @@ (:use #:cl) (:import-from #:40ants-doc/themes/api #:render-css) - (:import-from #:lass)) + (:import-from #:lass) + (:import-from #:40ants-doc/commondoc/html + #:with-html) + (:import-from #:40ants-doc/utils + #:make-relative-path) + (:import-from #:40ants-doc/rewrite) + (:export #:default-theme)) (in-package 40ants-doc/themes/default) @@ -135,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% @@ -185,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")) @@ -198,17 +215,6 @@ (.menu-block-title :font-size 90%) - (|#toc-header| - (a - :color "#777777")) - - (|#toc-footer| - :margin-left 1.5em - :margin-top 2em - (a - :font-size 80% - :color "#777777")) - (|#search-results| (.search (li @@ -216,3 +222,125 @@ (.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) + (with-html + (:html + (:head + (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-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) + (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/src/themes/docs.lisp b/src/themes/docs.lisp new file mode 100644 index 00000000..c2092335 --- /dev/null +++ b/src/themes/docs.lisp @@ -0,0 +1,138 @@ +(uiop:define-package #:40ants-doc/themes/docs + (:use #:cl) + (:import-from #:40ants-doc/themes/api + #:render-css + #:render-page + #:render-html-head + #:render-page-header + #:render-page-footer + #:render-content + #:render-sidebar + #:render-sidebar-header + #:render-sidebar-footer + #:render-sidebar-content + #:render-toc + #:render-search-form) + (:import-from #:lass) + (:import-from #:40ants-doc/commondoc/html + #:with-html) + (:import-from #:40ants-doc/utils + #:make-relative-path) + (:import-from #:40ants-doc/rewrite) + (:import-from #:40ants-doc + #:defsection) + (:import-from #:40ants-doc/themes/default) + (:import-from #:40ants-doc/themes/light) + (:import-from #:40ants-doc/themes/dark) + (:export #:default-theme)) +(in-package 40ants-doc/themes/docs) + + +(defsection @defining-a-theme (:title "Defining a Custom Theme" + :ignore-words ("HEAD" + "40A")) + "Out of the box, 40ANTS-DOC system supports three color themes: + + - 40ANTS-DOC/THEMES/DEFAULT:DEFAULT-THEME + - 40ANTS-DOC/THEMES/LIGHT:LIGHT-THEME + - 40ANTS-DOC/THEMES/DARK:DARK-THEME + + You can pass these names as THEME argument to the 40ANTS-DOC/BUILDER:RENDER-TO-FILES + function. Or you can define your own theme. + + Theme allows to control HTML page rendering, colors and code highlighting. + + ## Changing Colors + + The simplest way to customize theme is to redefine some colors using CSS. + Here is how to set orange page background: + + ```lisp + (defclass my-theme (default-theme) + ()) + + (defmethod 40ants-doc/themes/api:render-css ((theme my-theme)) + (concatenate + 'string + (call-next-method) + + (lass:compile-and-write + `(body + :background orange)))) + ``` + + Also you might want to redefine a color theme for code highlighter: + + ``` + (defmethod 40ants-doc/themes/api:highlight-theme ((theme my-theme)) + \"atom-one-light\") + ``` + + Talking about code highlighting, you can also redefine a list of + languages to highlight: + + ```lisp + (defmethod 40ants-doc/themes/api:highlight-languages ((theme my-theme)) + (list \"lisp\" + \"python\" + \"bash\")) + ``` + + ## Changing Page Layout + + The main entry-point for page rendering is + RENDER-PAGE generic-function. It calls all other + rendering functions. + + If you are inheriting your theme class from 40ANTS-DOC/THEMES/DEFAULT:DEFAULT-THEME, + then rendering functions will be called in the following order: + + ![Page Rendering Flow](static/rendering.png{width=600}) + + On this page stripes on the right demonstrate order in which different rendering functions will be called: + + - green is [RENDER-PAGE][generic-function]; + - blue is [RENDER-PAGE-HEADER][generic-function]; + - violet is [RENDER-SIDEBAR][generic-function] + - red is [RENDER-SIDEBAR-HEADER][generic-function] + - yellow is [RENDER-SIDEBAR-CONTENT][generic-function]; + - orange is [RENDER-SIDEBAR-FOOTER][generic-function]; + - salad green is [RENDER-CONTENT][generic-function]; + - pink is [RENDER-PAGE-FOOTER][generic-function]. + + Some of these methods might call [RENDER-TOC][generic-function] and + [RENDER-SEARCH-FORM][generic-function] to display a table of content + and a table form. Also, you might want to redefine RENDER-HTML-HEAD generic-function + to change html page metadata such as included stylesheets and js files, page title, etc. + + If you want to introduce changes, it is better to inherit from existing theme class + and to define a few methods to change only needed properties. For example, here is + a [theme I've made][my-theme] for all 40Ants projects. I've added header, footer and made colors match + the main site. + + [my-theme]: https://github.com/40ants/40ants-doc-theme-40ants/blob/master/theme.lisp + + ## Available Themes" + + (40ants-doc/themes/default:default-theme class) + (40ants-doc/themes/light:light-theme class) + (40ants-doc/themes/dark:dark-theme class) + + "## Theme Definition Protocol" + + (40ants-doc/themes/api:highlight-languages generic-function) + (40ants-doc/themes/api:highlight-theme generic-function) + + (40ants-doc/themes/api:render-css generic-function) + + (render-page generic-function) + (render-html-head generic-function) + (render-page-header generic-function) + (render-page-footer generic-function) + (render-content generic-function) + (render-sidebar generic-function) + (render-sidebar-header generic-function) + (render-sidebar-footer generic-function) + (render-sidebar-content generic-function) + (render-toc generic-function) + (render-search-form generic-function)) diff --git a/src/themes/light.lisp b/src/themes/light.lisp new file mode 100644 index 00000000..c61c9c55 --- /dev/null +++ b/src/themes/light.lisp @@ -0,0 +1,43 @@ +(defpackage #:40ants-doc/themes/light + (:use #:cl) + (:import-from #:40ants-doc/themes/default + #:default-theme) + (:import-from #:lass) + (:import-from #:40ants-doc/themes/api) + (:export #:light-theme)) +(in-package 40ants-doc/themes/light) + + +(defclass light-theme (default-theme) + ()) + +(defmethod 40ants-doc/themes/api:render-css ((theme light-theme)) + (let ((background "#FFFEFB") + (font-color "#333")) + (concatenate + 'string + (call-next-method) + + (lass:compile-and-write + `(body + :color ,font-color + + ((:or h1 h2 h3 h4 h5 h6) + :color ,font-color + :border-bottom none) + + (.sidebar + :background ,background + :box-shadow inset -3px 0 3px 0px "#777" + (.page-toc + (a + :color "#333")) + (.toc-active + :background ,font-color + ) + ((.toc-active > a) + :color ,background))))))) + +(defmethod 40ants-doc/themes/api:highlight-theme ((theme light-theme)) + "atom-one-light") + 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 diff --git a/static/rendering.png b/static/rendering.png new file mode 100644 index 00000000..307231e2 Binary files /dev/null and b/static/rendering.png differ diff --git a/static/rendering.skt/Layer~0.png b/static/rendering.skt/Layer~0.png new file mode 100644 index 00000000..1bcc3258 Binary files /dev/null and b/static/rendering.skt/Layer~0.png differ diff --git a/static/rendering.skt/Layer~1.png b/static/rendering.skt/Layer~1.png new file mode 100644 index 00000000..5a6ece62 Binary files /dev/null and b/static/rendering.skt/Layer~1.png differ diff --git a/static/rendering.skt/Layer~2.png b/static/rendering.skt/Layer~2.png new file mode 100644 index 00000000..73a3b2b0 Binary files /dev/null and b/static/rendering.skt/Layer~2.png differ diff --git a/static/rendering.skt/Properties.plist b/static/rendering.skt/Properties.plist new file mode 100644 index 00000000..6693e0fc --- /dev/null +++ b/static/rendering.skt/Properties.plist @@ -0,0 +1,229 @@ + + + + + Color0 + + 0.0 + 0.0 + 0.0 + 1 + + Color1 + + 0.87749642133712769 + 0.39214602112770081 + 0.53769022226333618 + 1 + + Colors + + + 219 + 22 + 8 + + + 238 + 85 + 9 + + + 118 + 66 + 36 + + + 201 + 122 + 69 + + + 239 + 198 + 159 + + + 241 + 155 + 26 + + + 247 + 194 + 23 + + + 242 + 231 + 81 + + + 207 + 220 + 23 + + + 175 + 210 + 69 + + + 80 + 155 + 52 + + + 9 + 98 + 13 + + + 151 + 202 + 202 + + + 120 + 178 + 217 + + + 59 + 140 + 207 + + + 46 + 92 + 191 + + + 15 + 50 + 144 + + + 100 + 23 + 186 + + + 168 + 72 + 235 + + + 193 + 106 + 231 + + + 177 + 66 + 151 + + + 224 + 94 + 133 + + + 235 + 126 + 155 + + + 255 + 197 + 209 + + + 164 + 8 + 0 + + + 255 + 255 + 255 + + + 242 + 238 + 231 + + + 192 + 192 + 192 + + + 128 + 128 + 128 + + + 0 + 0 + 0 + + + LayerIndex + 2 + Layers + + + AlphaLocked + + CompositingMode + 0 + File + Layer~0.png + Hidden + + Opacity + 100 + + + AlphaLocked + + CompositingMode + 0 + File + Layer~1.png + Hidden + + Opacity + 100 + + + AlphaLocked + + CompositingMode + 0 + File + Layer~2.png + Hidden + + Opacity + 100 + + + Orientation + 1 + Paper + Pressgrain + PaperColor + + 255 + 255 + 255 + 255 + + Version + 1.0 + penbrush + 2 + + diff --git a/static/rendering.skt/QuickLook/Preview.jpg b/static/rendering.skt/QuickLook/Preview.jpg new file mode 100644 index 00000000..d9431aef Binary files /dev/null and b/static/rendering.skt/QuickLook/Preview.jpg differ diff --git a/static/rendering.skt/QuickLook/Thumbnail.png b/static/rendering.skt/QuickLook/Thumbnail.png new file mode 100644 index 00000000..c1d883b7 Binary files /dev/null and b/static/rendering.skt/QuickLook/Thumbnail.png differ 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"); }) } diff --git a/test/data/baseline/METADATA b/test/data/baseline/METADATA new file mode 100644 index 00000000..223aa001 --- /dev/null +++ b/test/data/baseline/METADATA @@ -0,0 +1,2 @@ +languages: bash, css, json, lisp, markdown, plaintext, xml, yaml +theme: atom-one-dark 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> -
-
- - - - - -