├── links ├── rss.xml ├── main.css ├── skeleton.css └── normalize.css ├── static ├── .nojekyll ├── CNAME ├── .well-known │ └── webfinger ├── highlight.min.css └── highlight.min.js ├── .projectile ├── .gitignore ├── src ├── test.lua ├── templates │ ├── item.tpl.rss │ ├── feed.tpl.rss │ ├── head.tpl.html │ └── footer.tpl.html ├── plugins │ └── energy.sh ├── utils.lua ├── mmx.lua └── markdown.lua ├── run.sh ├── README.md └── processImages.sh /links/rss.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.projectile: -------------------------------------------------------------------------------- 1 | - /docs 2 | -------------------------------------------------------------------------------- /static/CNAME: -------------------------------------------------------------------------------- 1 | mrshll.com -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | load_secrets.sh 2 | .DS_Store 3 | data/.obsidian 4 | unused_media.txt 5 | -------------------------------------------------------------------------------- /src/test.lua: -------------------------------------------------------------------------------- 1 | local markdown = require "markdown" 2 | local utils = require "utils" 3 | 4 | print(markdown('- _[[foo]]_')) 5 | -------------------------------------------------------------------------------- /src/templates/item.tpl.rss: -------------------------------------------------------------------------------- 1 | 2 | <![CDATA[ {{EntryName}} ]]> 3 | https://mrshll.com/{{EntryDestFileName}} 4 | https://mrshll.com/{{EntryDestFileName}} 5 | {{RSSDate}} 6 | 7 | 8 | -------------------------------------------------------------------------------- /static/.well-known/webfinger: -------------------------------------------------------------------------------- 1 | {"subject":"acct:mrshll@mstdn.social","aliases":["https://mstdn.social/@mrshll","https://mstdn.social/users/mrshll"],"links":[{"rel":"http://webfinger.net/rel/profile-page","type":"text/html","href":"https://mstdn.social/@mrshll"},{"rel":"self","type":"application/activity+json","href":"https://mstdn.social/users/mrshll"},{"rel":"http://ostatus.org/schema/1.0/subscribe","template":"https://mstdn.social/authorize_interaction?uri={uri}"}]} -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | CONTENT_DIR=$1 3 | SITE_DIR=$2 4 | 5 | if [ -z $CONTENT_DIR ] || [ -z $SITE_DIR ]; then 6 | echo "Usage: ./run.sh path/to/content path/to/site" 7 | exit 1 8 | fi 9 | 10 | bash build.sh $CONTENT_DIR $SITE_DIR 11 | 12 | if [[ $OSTYPE == 'darwin'* ]]; then 13 | while fswatch -1 $CONTENT_DIR; do 14 | bash build.sh $CONTENT_DIR $SITE_DIR 15 | done 16 | else 17 | while inotifywait -qqre modify $CONTENT_DIR; do 18 | bash build.sh $CONTENT_DIR $SITE_DIR 19 | done 20 | fi 21 | -------------------------------------------------------------------------------- /src/templates/feed.tpl.rss: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | <![CDATA[ mrshll.com ]]> 7 | https://mrshll.com 8 | 11 | {{Items}} 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MMX 2 | 3 | For information about mmx, see it in action at https://mrshll.com/mmx.html 4 | 5 | Previous version with different feature set, written in Go now lives [here](https://github.com/mrshll/mmx-go) for archival purposes. 6 | 7 | ## Dependencies 8 | 9 | - Lua 10 | - GNU `date` for generating RSS item dates 11 | - `find` 12 | - _Optional:_ `inotifywatch` via `inotify-tools` for live site recompiling. 13 | 14 | ## Running 15 | 16 | There are three main scripts: 17 | 1. `./build.sh path/to/content path/to/site` which compiles the site 18 | 1. `./run.sh path/to/content path/to/site` which recompiles the site when the src or data changes 19 | 1. `./processImages.sh path/to/content path/to/site` which processes the images with resizing, compression and (optional) dithering 20 | -------------------------------------------------------------------------------- /src/plugins/energy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . ./load_secrets.sh 4 | 5 | DATE_BIN=date 6 | if [[ $OSTYPE == 'darwin'* ]]; then 7 | DATE_BIN=gdate 8 | fi 9 | 10 | OUT=$1 11 | DATE_FMT="+%Y-%m-%d %H:%M:%S" 12 | end=$($DATE_BIN "$DATE_FMT") 13 | start=$($DATE_BIN -d "$END_DATE -30 days" "$DATE_FMT") 14 | 15 | url="https://monitoringapi.solaredge.com/site/1368783/energyDetails" 16 | 17 | energy=$(curl -G -s \ 18 | --data-urlencode "api_key=$SOLAR_EDGE_API_KEY" \ 19 | --data-urlencode "meters=PRODUCTION,CONSUMPTION" \ 20 | --data-urlencode "timeUnit=DAY" \ 21 | --data-urlencode "startTime=$start" \ 22 | --data-urlencode "endTime=$end" \ 23 | $url) 24 | 25 | productionWh=$(echo $energy | 26 | jq '.energyDetails.meters[] | [select(.type | contains("Production")).values[].value] | add | select(. != null)') 27 | 28 | echo "
" >$OUT 29 | echo "
30-day solar status
" >>$OUT 30 | echo "
$(expr $productionWh / 1000) kWh produced ⚡
" >>$OUT 31 | echo "
" >>$OUT 32 | -------------------------------------------------------------------------------- /static/highlight.min.css: -------------------------------------------------------------------------------- 1 | pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} 2 | [data-theme="dark"] { pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#ddd;background:#303030}.hljs-keyword,.hljs-link,.hljs-literal,.hljs-section,.hljs-selector-tag{color:#fff}.hljs-addition,.hljs-attribute,.hljs-built_in,.hljs-bullet,.hljs-name,.hljs-string,.hljs-symbol,.hljs-template-tag,.hljs-template-variable,.hljs-title,.hljs-type,.hljs-variable{color:#d88}.hljs-comment,.hljs-deletion,.hljs-meta,.hljs-quote{color:#979797}.hljs-doctag,.hljs-keyword,.hljs-literal,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-strong,.hljs-title,.hljs-type{font-weight:700}.hljs-emphasis{font-style:italic} } 3 | -------------------------------------------------------------------------------- /src/templates/head.tpl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | mrshll.com - {{EntryName}} 30 | 31 | 32 | 39 | 40 | 41 | 44 | 50 | 55 | 56 | -------------------------------------------------------------------------------- /src/templates/footer.tpl.html: -------------------------------------------------------------------------------- 1 | 64 | -------------------------------------------------------------------------------- /processImages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script uses imagemagick to convert images in a folder (and it's 3 | # subfolders) into smaller sized variants. 4 | 5 | # This script is a remixed version of Clemens Scott's 6 | # https://git.sr.ht/~rostiger/batchResize/ used on site https://nchrs.xyz 7 | 8 | # Use with care and backup your images! 9 | # ----------------------------------------------------------------------------- 10 | CONTENT_DIR=$1 11 | SITE_DIR=$2 12 | IMG_PATH=$3 13 | 14 | if [ -z $CONTENT_DIR ] || [ -z $SITE_DIR ]; then 15 | echo "Usage: ./processImages.sh path/to/content path/to/site [path/to/img]" 16 | exit 1 17 | fi 18 | 19 | # path where the original images are located 20 | SRC="$CONTENT_DIR/media" 21 | # path where the images will be stored 22 | DST="$SITE_DIR/media" 23 | 24 | # sizes to convert to 25 | SIZES=(360 720) 26 | MAXWIDTH=2400 27 | #dithering 28 | COLORS=16 29 | 30 | function resize() { 31 | 32 | # Security check to prevent an endless loop when 33 | # $DST is inside $SRC (don't do that!) 34 | [[ $file == *"${DST}/*"* ]] && continue 35 | 36 | for file in $1; do 37 | # skip file if it doesn't exist 38 | [ -f "$file" ] || continue 39 | 40 | path=$(dirname $file) # just/the/path 41 | name=$(basename $file) # filename.ext 42 | fileBase="${name%%.*}" # filename 43 | fileExt="${name#*.}" # ext 44 | 45 | if ! grep -q -r "$name" $DST/../; then 46 | echo "${file} not used, skipping" 47 | echo "${file}" >>unused_media.txt 48 | continue 49 | fi 50 | 51 | # substitute source path with destination path 52 | # ${firstString/pattern/secondString} 53 | dst="${path/$SRC/$DST}" 54 | 55 | # existing images are skipped (delete images if they were updated) 56 | # create the output path (and parents) if it doesn't exist 57 | if [[ ! -d "$dst" ]]; then 58 | mkdir -p $dst 59 | fi 60 | 61 | # copy the file as is if it doesn't have the right extension 62 | if [[ "$fileExt" != "jpg" && "$fileExt" != "jpeg" && "$fileExt" != "png" && "$fileExt" != "MP.jpg" ]]; then 63 | cp -r $file $dst 64 | echo "Copied ${file}" 65 | continue 66 | fi 67 | 68 | # create smaller sizes for responsive image selection 69 | echo $file 70 | # get the width of the image 71 | width=$(identify -format "%w" "$file") >/dev/null 72 | for size in "${SIZES[@]}"; do 73 | # define output path and file 74 | output="$dst/$fileBase-${size}.${fileExt}" 75 | if [[ ! -f $output ]]; then 76 | # resize only if original image is greater than or equal to (ge) the current size 77 | if [[ $width -ge $size ]]; then 78 | echo -n "| ${size} " 79 | convert $file -strip -auto-orient -resize $size -dither FloydSteinberg -colors $COLORS $output 80 | else 81 | #dither only 82 | echo -n "| ${width} " 83 | convert $file -strip -auto-orient -dither FloydSteinberg -colors $COLORS $output 84 | fi 85 | else 86 | echo -n "| ----- " 87 | fi 88 | done 89 | 90 | # Finally also strip the original image of it's EXIF data 91 | # and resize it to a max width of 1200 92 | output="$dst/$name" 93 | if [[ ! -f $output ]]; then 94 | if [[ $width -gt $MAXWIDTH ]]; then 95 | convert $file -strip -auto-orient -resize $MAXWIDTH $output 96 | echo -n "| ${MAXWIDTH} " 97 | else 98 | convert $file -strip -auto-orient $output 99 | echo -n "| ${width} " 100 | fi 101 | else 102 | echo -n "| ----- " 103 | fi 104 | echo -en "|\n" 105 | done 106 | } 107 | 108 | if [[ -f $IMG_PATH ]]; then 109 | resize $IMG_PATH 110 | else 111 | mkdir $DST 112 | echo "" > unused_media.txt 113 | # find all file in the source folder and run resize() on each 114 | find $SRC | while read file; do resize "${file}"; done 115 | fi 116 | -------------------------------------------------------------------------------- /src/utils.lua: -------------------------------------------------------------------------------- 1 | local utils = {} 2 | 3 | -- file io 4 | function utils.file_exists(path) 5 | local file = io.open(path, "r") 6 | if file ~= nil then 7 | file:close() 8 | return true 9 | else 10 | return false 11 | end 12 | end 13 | 14 | function utils.read_file(path) 15 | local file = io.open(path, "rb") -- r read mode and b binary mode 16 | if not file then 17 | error("unable to open file for reading at " .. path) 18 | end 19 | local content = file:read "*a" -- *a or *all reads the whole file 20 | file:close() 21 | return content 22 | end 23 | 24 | function utils.write_file(path, content) 25 | local file = io.open(path, "w") 26 | if not file then 27 | error("unable to open file for writing at " .. path) 28 | end 29 | file:write(content) 30 | file:close() 31 | end 32 | 33 | function utils.delete_file(path) 34 | assert(os.remove(path)) 35 | end 36 | 37 | function utils.list_folders(directory) 38 | local pfile = io.popen('cd ' .. directory .. ' && find ' .. directory .. ' -type d') 39 | if not pfile then 40 | error("unable to list folders in directory " .. directory) 41 | end 42 | 43 | local folder_names = {} 44 | for folder_name in pfile:lines() do 45 | folder_name = folder_name:sub(#directory + 1) 46 | if not utils.starts_with(folder_name, '.') and #folder_name > 0 then 47 | table.insert(folder_names, folder_name) 48 | end 49 | end 50 | 51 | pfile:close() 52 | return folder_names 53 | end 54 | 55 | function utils.list_files(directory, extension) 56 | -- resulting command is: 57 | -- find [dir] -type f -name "*.[ext]" 58 | local pfile = io.popen('find -L ' .. directory .. ' -type f -name "*' .. (extension or "") .. '"') 59 | if not pfile then 60 | error("unable to list files in directory " .. directory .. " with extension " .. extension) 61 | end 62 | 63 | local file_names = {} 64 | for file_name in pfile:lines() do 65 | file_name = file_name:sub(#directory + 1) 66 | table.insert(file_names, file_name) 67 | end 68 | 69 | pfile:close() 70 | return file_names 71 | end 72 | 73 | -- strings 74 | 75 | function utils.starts_with(str, start) 76 | return str:sub(1, #start) == start 77 | end 78 | 79 | function utils.ends_with(str, ending) 80 | return ending == "" or str:sub(- #ending) == ending 81 | end 82 | 83 | function utils.lines(str) 84 | if str:sub(-1) ~= "\n" then 85 | str = str .. "\n" 86 | end 87 | return str:gmatch("(.-)\n") 88 | end 89 | 90 | function utils.split(input, sep) 91 | if sep == nil then 92 | sep = "%s" 93 | end 94 | local t = {} 95 | for str in string.gmatch(input, "([^" .. sep .. "]+)") do 96 | table.insert(t, str) 97 | end 98 | return t 99 | end 100 | 101 | function utils.capitalize(str) 102 | return (str:gsub("^%l", string.upper)) 103 | end 104 | 105 | function utils.title_case(str) 106 | return utils.capitalize(str:gsub(" %l", string.upper)) 107 | end 108 | 109 | function utils.slugify(str) 110 | return (str:gsub("[%s%p]", "_")):lower() 111 | end 112 | 113 | -- tables 114 | 115 | function utils.has_keys(table, keys) 116 | for _, key in pairs(keys) do 117 | if table[key] == nil then 118 | return false 119 | end 120 | end 121 | 122 | return true 123 | end 124 | 125 | function utils.get_key_case_insensitive(table, key) 126 | return table[key] or table[utils.capitalize(key)] or table[key:lower()] or table[key:upper()] or 127 | table[utils.title_case(key)] 128 | end 129 | 130 | function utils.spairs(t, order) 131 | -- collect the keys 132 | local keys = {} 133 | for k in pairs(t) do 134 | keys[#keys + 1] = k 135 | end 136 | 137 | -- if order function given, sort by it by passing the table and keys a, b, 138 | -- otherwise just sort the keys 139 | if order then 140 | table.sort(keys, function(a, b) 141 | return order(t, a, b) 142 | end) 143 | else 144 | table.sort(keys) 145 | end 146 | 147 | -- return the iterator function 148 | local i = 0 149 | return function() 150 | i = i + 1 151 | if keys[i] then 152 | return keys[i], t[keys[i]] 153 | end 154 | end 155 | end 156 | 157 | function utils.dump(o) 158 | if type(o) == 'table' then 159 | local s = '{ ' 160 | for k, v in pairs(o) do 161 | if type(k) ~= 'number' then 162 | k = '"' .. k .. '"' 163 | end 164 | s = s .. '[' .. k .. '] = ' .. utils.dump(v) .. ',' 165 | end 166 | return s .. '} ' 167 | else 168 | return tostring(o) 169 | end 170 | end 171 | 172 | -- dates 173 | function utils.today() 174 | local date_table = os.date("*t") 175 | local year, month, day = date_table.year, date_table.month, date_table.day -- date_table.wday to date_table.day 176 | return string.format("%d-%02d-%02d", year, month, day) 177 | end 178 | 179 | function utils.rss_date(date_str) 180 | local handle = io.popen("gdate -R -d " .. date_str) 181 | if not handle then 182 | error("unable to run command in rss_date") 183 | end 184 | local result = handle:read("*a") 185 | handle:close() 186 | return result 187 | end 188 | 189 | function utils.process_image(data_dir, site_dir, img_path) 190 | local cmd = "bash ../processImages.sh " .. data_dir .. " " .. site_dir .. " " .. img_path 191 | print(cmd) 192 | local handle = io.popen(cmd) 193 | if not handle then 194 | error("unable to process image " .. img_path) 195 | end 196 | local result = handle:read("*a") 197 | print(result) 198 | handle:close() 199 | return result 200 | end 201 | 202 | return utils 203 | -------------------------------------------------------------------------------- /links/main.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --bg-color: white; 3 | --text-color: #4b4b4b; 4 | --header-color: #353535; 5 | --link-color: #3d7496; 6 | --highlight-color: #fff9b5; 7 | --accent-color: tomato; 8 | --bg-contrast-color: lightgrey; 9 | --mono-font: monospace; 10 | --sans-font: sans-serif; 11 | } 12 | 13 | [data-theme="dark"] { 14 | --bg-color: #353535; 15 | --text-color: #b4b4b4; 16 | --header-color: #cacaca; 17 | --link-color: #93bdd8; 18 | --highlight-color: darkslategrey; 19 | --bg-contrast-color: black; 20 | } 21 | 22 | body { 23 | font-size: 1.6rem; 24 | font-family: var(--sans-font); 25 | color: var(--text-color); 26 | background-color: var(--bg-color); 27 | font-weight: 400; 28 | line-height: 1.4; 29 | } 30 | 31 | a { 32 | text-decoration: none; 33 | color: var(--link-color); 34 | } 35 | 36 | a:hover { 37 | background-color: var(--link-color); 38 | color: var(--bg-color); 39 | } 40 | 41 | .footnote { 42 | font-size: 75%; 43 | margin-bottom: 1rem; 44 | } 45 | 46 | h1, 47 | h2, 48 | h3, 49 | h4, 50 | h5, 51 | h6 { 52 | font-family: var(--mono-font); 53 | font-weight: 700; 54 | color: var(--header-color); 55 | margin-top: 2rem; 56 | margin-bottom: 1rem; 57 | } 58 | 59 | h1 { 60 | text-transform: uppercase; 61 | text-decoration: underline; 62 | } 63 | 64 | mark { 65 | background-color: var(--highlight-color); 66 | } 67 | 68 | header { 69 | position: relative; 70 | padding-bottom: 2rem; 71 | border-bottom: 1.5px dotted; 72 | } 73 | 74 | #fm { 75 | position: absolute; 76 | top: 0; 77 | right: 0; 78 | } 79 | 80 | nav { 81 | font-size: 1.6rem; 82 | display: flex; 83 | overflow-x: auto; 84 | } 85 | 86 | nav details summary { 87 | margin-left: -1.2rem; 88 | cursor: pointer; 89 | } 90 | 91 | nav details summary::before { 92 | content: "Show all..."; 93 | } 94 | nav details[open] summary::before { 95 | content: "Hide..."; 96 | } 97 | 98 | nav details summary::marker { 99 | display: none; 100 | } 101 | 102 | hr { 103 | border: none; 104 | height: 0.4rem; 105 | width: 10rem; 106 | background-color: var(--text-color); 107 | overflow: visible; 108 | text-align: right; 109 | height: 5px; 110 | margin-left: 0; 111 | } 112 | 113 | p { 114 | margin-bottom: 1.2rem; 115 | } 116 | 117 | s { 118 | text-decoration-style: solid; 119 | text-decoration-color: var(--accent-color); 120 | } 121 | 122 | ol, 123 | ul, 124 | dl { 125 | margin: 1rem 0 1rem 2rem; 126 | list-style-position: outside; 127 | } 128 | 129 | li { 130 | margin-bottom: 0.4rem; 131 | } 132 | 133 | nav ul { 134 | padding: 0; 135 | margin: 0 2rem 0 0; 136 | } 137 | 138 | nav ul li { 139 | list-style-type: none; 140 | white-space: pre; 141 | margin-bottom: 0.4rem; 142 | } 143 | 144 | li.sublist-container::marker { 145 | content: ""; 146 | } 147 | 148 | footer { 149 | padding: 0 4.6rem; 150 | max-width: 624px; 151 | position: relative; 152 | } 153 | 154 | .footer-row { 155 | padding: 3.6rem 0 0; 156 | border-top: 1.5px dotted; 157 | } 158 | 159 | blockquote { 160 | border-left: 4px solid var(--bg-contrast-color); 161 | padding-left: 2rem; 162 | margin-left: 2rem; 163 | } 164 | 165 | figure { 166 | display: table; 167 | margin: 0 0 1.6rem; 168 | background-color: var(--bg-contrast-color); 169 | } 170 | 171 | figcaption { 172 | display: table-caption; 173 | caption-side: bottom; 174 | background-color: var(--bg-contrast-color); 175 | padding: 0.2rem; 176 | text-align: center; 177 | text-wrap: balance; 178 | } 179 | 180 | code, 181 | blockquote cite { 182 | background-color: var(--bg-contrast-color); 183 | border: none; 184 | overflow: auto; 185 | } 186 | 187 | footer .footer-row > * { 188 | display: inline-block; 189 | margin-right: 1rem; 190 | margin-bottom: 3rem; 191 | vertical-align: middle; 192 | font-size: 1.6rem; 193 | } 194 | 195 | [data-theme="dark"] footer img { 196 | filter: invert(100%); 197 | } 198 | 199 | dl dd, 200 | details { 201 | margin-top: 0.2rem; 202 | margin-bottom: 0.4rem; 203 | } 204 | 205 | .incoming { 206 | display: table; 207 | } 208 | 209 | .content { 210 | max-width: 624px; 211 | padding: 2rem 4.6rem; 212 | font-size: 1.6rem; 213 | position: relative; 214 | } 215 | 216 | main { 217 | margin: 2rem 0; 218 | } 219 | 220 | main details { 221 | display: inline-block; 222 | border: 1px solid var(--bg-contrast-color); 223 | border-radius: 0.4rem; 224 | padding: 0.4rem 1rem 0; 225 | margin-right: 0.4rem; 226 | } 227 | 228 | main summary { 229 | margin: -0.4rem -1rem 0; 230 | padding: 0.4rem 1rem; 231 | } 232 | 233 | main details[open] { 234 | padding: 0.4rem 1rem; 235 | display: block; 236 | } 237 | 238 | main details[open] summary { 239 | border-bottom: 1px solid var(--bg-contrast-color); 240 | margin-bottom: 0.5em; 241 | } 242 | 243 | .content img, 244 | .content video { 245 | max-width: 100%; 246 | margin-left: 0; 247 | margin-right: 0; 248 | margin-top: 0; 249 | padding-bottom: 0; 250 | padding-left: 0; 251 | padding-right: 0; 252 | padding-top: 0; 253 | display: block; 254 | } 255 | 256 | .content video { 257 | margin-bottom: 1.6rem; 258 | } 259 | 260 | #low-tech-webring:hover table { 261 | visibility: visible; 262 | } 263 | 264 | #low-tech-webring table { 265 | position: fixed; 266 | visibility: hidden; 267 | padding: 0 1rem; 268 | display: block; 269 | border: 1px solid var(--bg-contrast-color); 270 | background-color: var(--bg-color); 271 | left: 0; 272 | right: 0; 273 | bottom: 0; 274 | } 275 | 276 | #low-tech-webring table td { 277 | border: 0; 278 | } 279 | 280 | #lightswitch { 281 | position: absolute; 282 | height: 4rem; 283 | top: calc(50% - 2rem); 284 | right: 4rem; 285 | } 286 | 287 | #lightswitch input, 288 | #lightswitch label { 289 | position: absolute; 290 | } 291 | 292 | #lightswitch input { 293 | display: none; 294 | } 295 | 296 | #lightswitch input + label:after { 297 | font-size: 2rem; 298 | content: "💡"; 299 | } 300 | 301 | #lightswitch input:checked + label:after { 302 | content: "🕯️"; 303 | } 304 | 305 | article { 306 | border: 1px solid; 307 | padding: 20px; 308 | margin-left: -20px; 309 | margin-right: -20px; 310 | } 311 | 312 | article h2 { 313 | display: inline; 314 | } 315 | 316 | article h2 + a { 317 | margin-left: 10px; 318 | } 319 | 320 | @media screen and (max-width: 1000px) { 321 | html { 322 | font-size: 12px; 323 | } 324 | 325 | .content { 326 | padding: 2rem 2.2rem; 327 | } 328 | 329 | footer { 330 | padding: 2rem 2.2rem 0; 331 | } 332 | } 333 | -------------------------------------------------------------------------------- /links/skeleton.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Skeleton V2.0.4 3 | * Copyright 2014, Dave Gamache 4 | * www.getskeleton.com 5 | * Free to use under the MIT license. 6 | * http://www.opensource.org/licenses/mit-license.php 7 | * 12/29/2014 8 | */ 9 | 10 | /* Table of contents 11 | –––––––––––––––––––––––––––––––––––––––––––––––––– 12 | - Grid 13 | - Base Styles 14 | - Typography 15 | - Links 16 | - Buttons 17 | - Forms 18 | - Lists 19 | - Code 20 | - Tables 21 | - Spacing 22 | - Utilities 23 | - Clearing 24 | - Media Queries 25 | */ 26 | 27 | /* Grid 28 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 29 | .container { 30 | position: relative; 31 | width: 100%; 32 | max-width: 960px; 33 | margin: 0 auto; 34 | padding: 0 20px; 35 | box-sizing: border-box; 36 | } 37 | .column, 38 | .columns { 39 | width: 100%; 40 | float: left; 41 | box-sizing: border-box; 42 | } 43 | 44 | /* For devices larger than 400px */ 45 | @media (min-width: 400px) { 46 | .container { 47 | width: 85%; 48 | padding: 0; 49 | } 50 | } 51 | 52 | /* Base Styles 53 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 54 | /* NOTE 55 | html is set to 62.5% so that all the REM measurements throughout Skeleton 56 | are based on 10px sizing. So basically 1.5rem = 15px :) */ 57 | html { 58 | font-size: 62.5%; 59 | } 60 | body { 61 | font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ 62 | line-height: 1.6; 63 | font-weight: 400; 64 | font-family: 'Raleway', 'HelveticaNeue', 'Helvetica Neue', Helvetica, Arial, sans-serif; 65 | color: #222; 66 | } 67 | 68 | 69 | /* Buttons 70 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 71 | .button, 72 | button, 73 | input[type='submit'], 74 | input[type='reset'], 75 | input[type='button'] { 76 | display: inline-block; 77 | height: 38px; 78 | padding: 0 30px; 79 | color: #555; 80 | text-align: center; 81 | font-size: 11px; 82 | font-weight: 600; 83 | line-height: 38px; 84 | letter-spacing: 0.1rem; 85 | text-transform: uppercase; 86 | text-decoration: none; 87 | white-space: nowrap; 88 | background-color: transparent; 89 | border-radius: 4px; 90 | border: 1px solid #bbb; 91 | cursor: pointer; 92 | box-sizing: border-box; 93 | } 94 | .button:hover, 95 | button:hover, 96 | input[type='submit']:hover, 97 | input[type='reset']:hover, 98 | input[type='button']:hover, 99 | .button:focus, 100 | button:focus, 101 | input[type='submit']:focus, 102 | input[type='reset']:focus, 103 | input[type='button']:focus { 104 | color: #333; 105 | border-color: #888; 106 | outline: 0; 107 | } 108 | .button.button-primary, 109 | button.button-primary, 110 | input[type='submit'].button-primary, 111 | input[type='reset'].button-primary, 112 | input[type='button'].button-primary { 113 | color: #fff; 114 | background-color: #33c3f0; 115 | border-color: #33c3f0; 116 | } 117 | .button.button-primary:hover, 118 | button.button-primary:hover, 119 | input[type='submit'].button-primary:hover, 120 | input[type='reset'].button-primary:hover, 121 | input[type='button'].button-primary:hover, 122 | .button.button-primary:focus, 123 | button.button-primary:focus, 124 | input[type='submit'].button-primary:focus, 125 | input[type='reset'].button-primary:focus, 126 | input[type='button'].button-primary:focus { 127 | color: #fff; 128 | background-color: #1eaedb; 129 | border-color: #1eaedb; 130 | } 131 | 132 | /* Forms 133 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 134 | input[type='email'], 135 | input[type='number'], 136 | input[type='search'], 137 | input[type='text'], 138 | input[type='tel'], 139 | input[type='url'], 140 | input[type='password'], 141 | textarea, 142 | select { 143 | height: 38px; 144 | padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ 145 | background-color: #fff; 146 | border: 1px solid #d1d1d1; 147 | border-radius: 4px; 148 | box-shadow: none; 149 | box-sizing: border-box; 150 | } 151 | /* Removes awkward default styles on some inputs for iOS */ 152 | input[type='email'], 153 | input[type='number'], 154 | input[type='search'], 155 | input[type='text'], 156 | input[type='tel'], 157 | input[type='url'], 158 | input[type='password'], 159 | textarea { 160 | -webkit-appearance: none; 161 | -moz-appearance: none; 162 | appearance: none; 163 | } 164 | textarea { 165 | min-height: 65px; 166 | padding-top: 6px; 167 | padding-bottom: 6px; 168 | } 169 | input[type='email']:focus, 170 | input[type='number']:focus, 171 | input[type='search']:focus, 172 | input[type='text']:focus, 173 | input[type='tel']:focus, 174 | input[type='url']:focus, 175 | input[type='password']:focus, 176 | textarea:focus, 177 | select:focus { 178 | border: 1px solid #33c3f0; 179 | outline: 0; 180 | } 181 | label, 182 | legend { 183 | display: block; 184 | margin-bottom: 0.5rem; 185 | font-weight: 600; 186 | } 187 | fieldset { 188 | padding: 0; 189 | border-width: 0; 190 | } 191 | input[type='checkbox'], 192 | input[type='radio'] { 193 | display: inline; 194 | } 195 | label > .label-body { 196 | display: inline-block; 197 | margin-left: 0.5rem; 198 | font-weight: normal; 199 | } 200 | 201 | /* Lists 202 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 203 | ul { 204 | list-style: circle inside; 205 | } 206 | ol { 207 | list-style: decimal inside; 208 | } 209 | ol, 210 | ul { 211 | padding-left: 0; 212 | margin-top: 0; 213 | } 214 | li { 215 | margin-bottom: 1rem; 216 | } 217 | 218 | /* Code 219 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 220 | code { 221 | padding: 0.2rem 0.5rem; 222 | margin: 0 0.2rem; 223 | font-size: 90%; 224 | white-space: nowrap; 225 | background: #f1f1f1; 226 | border: 1px solid #e1e1e1; 227 | border-radius: 4px; 228 | } 229 | pre > code { 230 | display: block; 231 | padding: 1rem 1.5rem; 232 | white-space: pre; 233 | } 234 | 235 | /* Tables 236 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 237 | th, 238 | td { 239 | padding: 12px 15px; 240 | text-align: left; 241 | border-bottom: 1px solid #e1e1e1; 242 | } 243 | th:first-child, 244 | td:first-child { 245 | padding-left: 0; 246 | } 247 | th:last-child, 248 | td:last-child { 249 | padding-right: 0; 250 | } 251 | 252 | /* Spacing 253 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 254 | button, 255 | .button { 256 | margin-bottom: 1rem; 257 | } 258 | input, 259 | textarea, 260 | select, 261 | fieldset { 262 | margin-bottom: 1.5rem; 263 | } 264 | pre, 265 | blockquote, 266 | dl, 267 | figure, 268 | table, 269 | p, 270 | ul, 271 | ol, 272 | form { 273 | margin-bottom: 2.5rem; 274 | } 275 | 276 | /* Utilities 277 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 278 | .u-full-width { 279 | width: 100%; 280 | box-sizing: border-box; 281 | } 282 | .u-max-full-width { 283 | max-width: 100%; 284 | box-sizing: border-box; 285 | } 286 | .u-pull-right { 287 | float: right; 288 | } 289 | .u-pull-left { 290 | float: left; 291 | } 292 | 293 | /* Misc 294 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 295 | hr { 296 | margin-top: 3rem; 297 | margin-bottom: 3.5rem; 298 | border-width: 0; 299 | border-top: 1px solid #e1e1e1; 300 | } 301 | 302 | /* Clearing 303 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 304 | 305 | /* Self Clearing Goodness */ 306 | .container:after, 307 | .row:after, 308 | .u-cf { 309 | content: ''; 310 | display: table; 311 | clear: both; 312 | } 313 | 314 | /* Media Queries 315 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ 316 | /* 317 | Note: The best way to structure the use of media queries is to create the queries 318 | near the relevant code. For example, if you wanted to change the styles for buttons 319 | on small devices, paste the mobile query code up in the buttons section and style it 320 | there. 321 | */ 322 | 323 | /* Larger than mobile */ 324 | @media (min-width: 400px) { 325 | } 326 | 327 | /* Larger than phablet (also point when grid becomes active) */ 328 | @media (min-width: 550px) { 329 | } 330 | 331 | /* Larger than tablet */ 332 | @media (min-width: 750px) { 333 | } 334 | 335 | /* Larger than desktop */ 336 | @media (min-width: 1000px) { 337 | } 338 | 339 | /* Larger than Desktop HD */ 340 | @media (min-width: 1200px) { 341 | } 342 | -------------------------------------------------------------------------------- /links/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling 6 | * user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section { 45 | display: block; 46 | } 47 | 48 | /** 49 | * 1. Correct `inline-block` display not defined in IE 8/9. 50 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 51 | */ 52 | 53 | audio, 54 | canvas, 55 | progress, 56 | video { 57 | display: inline-block; /* 1 */ 58 | vertical-align: baseline; /* 2 */ 59 | } 60 | 61 | /** 62 | * Prevent modern browsers from displaying `audio` without controls. 63 | * Remove excess height in iOS 5 devices. 64 | */ 65 | 66 | audio:not([controls]) { 67 | display: none; 68 | height: 0; 69 | } 70 | 71 | /** 72 | * Address `[hidden]` styling not present in IE 8/9/10. 73 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. 74 | */ 75 | 76 | [hidden], 77 | template { 78 | display: none; 79 | } 80 | 81 | /* Links 82 | ========================================================================== */ 83 | 84 | /** 85 | * Remove the gray background color from active links in IE 10. 86 | */ 87 | 88 | a { 89 | background-color: transparent; 90 | } 91 | 92 | /** 93 | * Improve readability when focused and also mouse hovered in all browsers. 94 | */ 95 | 96 | a:active, 97 | a:hover { 98 | outline: 0; 99 | } 100 | 101 | /* Text-level semantics 102 | ========================================================================== */ 103 | 104 | /** 105 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 106 | */ 107 | 108 | abbr[title] { 109 | border-bottom: 1px dotted; 110 | } 111 | 112 | /** 113 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 114 | */ 115 | 116 | b, 117 | strong { 118 | font-weight: bold; 119 | } 120 | 121 | /** 122 | * Address styling not present in Safari and Chrome. 123 | */ 124 | 125 | dfn { 126 | font-style: italic; 127 | } 128 | 129 | /** 130 | * Address variable `h1` font-size and margin within `section` and `article` 131 | * contexts in Firefox 4+, Safari, and Chrome. 132 | */ 133 | 134 | h1 { 135 | font-size: 2em; 136 | margin: 0.67em 0; 137 | } 138 | 139 | /** 140 | * Address styling not present in IE 8/9. 141 | */ 142 | 143 | mark { 144 | background: #ff0; 145 | color: #000; 146 | } 147 | 148 | /** 149 | * Address inconsistent and variable font size in all browsers. 150 | */ 151 | 152 | small { 153 | font-size: 80%; 154 | } 155 | 156 | /** 157 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 158 | */ 159 | 160 | sub, 161 | sup { 162 | font-size: 75%; 163 | line-height: 0; 164 | position: relative; 165 | vertical-align: baseline; 166 | } 167 | 168 | sup { 169 | top: -0.5em; 170 | } 171 | 172 | sub { 173 | bottom: -0.25em; 174 | } 175 | 176 | /* Embedded content 177 | ========================================================================== */ 178 | 179 | /** 180 | * Remove border when inside `a` element in IE 8/9/10. 181 | */ 182 | 183 | img { 184 | border: 0; 185 | } 186 | 187 | /** 188 | * Correct overflow not hidden in IE 9/10/11. 189 | */ 190 | 191 | svg:not(:root) { 192 | overflow: hidden; 193 | } 194 | 195 | /* Grouping content 196 | ========================================================================== */ 197 | 198 | /** 199 | * Address margin not present in IE 8/9 and Safari. 200 | */ 201 | 202 | figure { 203 | margin: 1em 40px; 204 | } 205 | 206 | /** 207 | * Address differences between Firefox and other browsers. 208 | */ 209 | 210 | hr { 211 | -moz-box-sizing: content-box; 212 | box-sizing: content-box; 213 | height: 0; 214 | } 215 | 216 | /** 217 | * Contain overflow in all browsers. 218 | */ 219 | 220 | pre { 221 | overflow: auto; 222 | } 223 | 224 | /** 225 | * Address odd `em`-unit font size rendering in all browsers. 226 | */ 227 | 228 | code, 229 | kbd, 230 | pre, 231 | samp { 232 | font-family: monospace, monospace; 233 | font-size: 1em; 234 | } 235 | 236 | /* Forms 237 | ========================================================================== */ 238 | 239 | /** 240 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 241 | * styling of `select`, unless a `border` property is set. 242 | */ 243 | 244 | /** 245 | * 1. Correct color not being inherited. 246 | * Known issue: affects color of disabled elements. 247 | * 2. Correct font properties not being inherited. 248 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 249 | */ 250 | 251 | button, 252 | input, 253 | optgroup, 254 | select, 255 | textarea { 256 | color: inherit; /* 1 */ 257 | font: inherit; /* 2 */ 258 | margin: 0; /* 3 */ 259 | } 260 | 261 | /** 262 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 263 | */ 264 | 265 | button { 266 | overflow: visible; 267 | } 268 | 269 | /** 270 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 271 | * All other form control elements do not inherit `text-transform` values. 272 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 273 | * Correct `select` style inheritance in Firefox. 274 | */ 275 | 276 | button, 277 | select { 278 | text-transform: none; 279 | } 280 | 281 | /** 282 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 283 | * and `video` controls. 284 | * 2. Correct inability to style clickable `input` types in iOS. 285 | * 3. Improve usability and consistency of cursor style between image-type 286 | * `input` and others. 287 | */ 288 | 289 | button, 290 | html input[type="button"], /* 1 */ 291 | input[type="reset"], 292 | input[type="submit"] { 293 | -webkit-appearance: button; /* 2 */ 294 | cursor: pointer; /* 3 */ 295 | } 296 | 297 | /** 298 | * Re-set default cursor for disabled elements. 299 | */ 300 | 301 | button[disabled], 302 | html input[disabled] { 303 | cursor: default; 304 | } 305 | 306 | /** 307 | * Remove inner padding and border in Firefox 4+. 308 | */ 309 | 310 | button::-moz-focus-inner, 311 | input::-moz-focus-inner { 312 | border: 0; 313 | padding: 0; 314 | } 315 | 316 | /** 317 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 318 | * the UA stylesheet. 319 | */ 320 | 321 | input { 322 | line-height: normal; 323 | } 324 | 325 | /** 326 | * It's recommended that you don't attempt to style these elements. 327 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 328 | * 329 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 330 | * 2. Remove excess padding in IE 8/9/10. 331 | */ 332 | 333 | input[type='checkbox'], 334 | input[type='radio'] { 335 | box-sizing: border-box; /* 1 */ 336 | padding: 0; /* 2 */ 337 | } 338 | 339 | /** 340 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 341 | * `font-size` values of the `input`, it causes the cursor style of the 342 | * decrement button to change from `default` to `text`. 343 | */ 344 | 345 | input[type='number']::-webkit-inner-spin-button, 346 | input[type='number']::-webkit-outer-spin-button { 347 | height: auto; 348 | } 349 | 350 | /** 351 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 352 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome 353 | * (include `-moz` to future-proof). 354 | */ 355 | 356 | input[type='search'] { 357 | -webkit-appearance: textfield; /* 1 */ 358 | -moz-box-sizing: content-box; 359 | -webkit-box-sizing: content-box; /* 2 */ 360 | box-sizing: content-box; 361 | } 362 | 363 | /** 364 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 365 | * Safari (but not Chrome) clips the cancel button when the search input has 366 | * padding (and `textfield` appearance). 367 | */ 368 | 369 | input[type='search']::-webkit-search-cancel-button, 370 | input[type='search']::-webkit-search-decoration { 371 | -webkit-appearance: none; 372 | } 373 | 374 | /** 375 | * Define consistent border, margin, and padding. 376 | */ 377 | 378 | fieldset { 379 | border: 1px solid #c0c0c0; 380 | margin: 0 2px; 381 | padding: 0.35em 0.625em 0.75em; 382 | } 383 | 384 | /** 385 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 386 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 387 | */ 388 | 389 | legend { 390 | border: 0; /* 1 */ 391 | padding: 0; /* 2 */ 392 | } 393 | 394 | /** 395 | * Remove default vertical scrollbar in IE 8/9/10/11. 396 | */ 397 | 398 | textarea { 399 | overflow: auto; 400 | } 401 | 402 | /** 403 | * Don't inherit the `font-weight` (applied by a rule above). 404 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 405 | */ 406 | 407 | optgroup { 408 | font-weight: bold; 409 | } 410 | 411 | /* Tables 412 | ========================================================================== */ 413 | 414 | /** 415 | * Remove most spacing between table cells. 416 | */ 417 | 418 | table { 419 | border-collapse: collapse; 420 | border-spacing: 0; 421 | } 422 | 423 | td, 424 | th { 425 | padding: 0; 426 | } 427 | -------------------------------------------------------------------------------- /src/mmx.lua: -------------------------------------------------------------------------------- 1 | local markdown = require "markdown" 2 | local utils = require "utils" 3 | 4 | if not arg[1] or arg[1] == '' or not arg[2] or arg[2] == '' then 5 | error('usage: lua mmx.lua path/to/content path/to/site') 6 | end 7 | 8 | local SITE_NAME = 'mrshll.com' 9 | local INDEX_NAME = "index" 10 | local MIN_DATE = "0000-00-00" 11 | local MEDIA_DIR_NAME = 'media' 12 | local DATA_DIR = "../" .. arg[1] 13 | local SITE_DIR = "../" .. arg[2] 14 | local DATA_EXT = ".md" 15 | 16 | -- store all image paths to do a check to make sure they exist 17 | local media_paths = {} 18 | 19 | local function sub_entry_fields(str, entry) 20 | return str:gsub("{{(%w+)}}", { 21 | ["EntryBodyHtml"] = entry.body_html, 22 | ["EntryName"] = entry.name, 23 | ["EntryDate"] = entry.date, 24 | ["EntryDestFileName"] = entry.dest_file_name 25 | }) 26 | end 27 | 28 | local function render_head(entry) 29 | return sub_entry_fields(utils.read_file("templates/head.tpl.html"), entry) 30 | end 31 | 32 | local function render_footer() 33 | return utils.read_file("templates/footer.tpl.html") 34 | end 35 | 36 | local function make_sorted_entry_iterator(entries) 37 | return utils.spairs(entries, function(es, name_a, name_b) 38 | local entry_a = es[name_a] 39 | local entry_b = es[name_b] 40 | if entry_a.date or entry_b.date then 41 | return (entry_a.date or MIN_DATE) > (entry_b.date or MIN_DATE) 42 | else 43 | return name_a < name_b 44 | end 45 | end) 46 | end 47 | 48 | local function render_nav_section(entry, siblings) 49 | local acc = "" 73 | end 74 | 75 | local function render_nav(entry, entries) 76 | local acc = "" 77 | 78 | local children = {} 79 | for _, e in make_sorted_entry_iterator(entries) do 80 | if e.parent_name == entry.name and e.name ~= SITE_NAME then 81 | table.insert(children, e) 82 | end 83 | end 84 | acc = acc .. render_nav_section(nil, children) 85 | 86 | -- go until we are at root 87 | while entry.name ~= SITE_NAME do 88 | local siblings = {} 89 | local parent = nil 90 | for _, e in make_sorted_entry_iterator(entries) do 91 | if entry.parent_name == e.name then 92 | parent = e 93 | elseif e.parent_name == entry.parent_name then 94 | table.insert(siblings, e) 95 | end 96 | end 97 | acc = render_nav_section(entry, siblings) .. acc 98 | if parent == nil then 99 | error(entry.name .. "(" .. entry.src_path .. ") has no parent") 100 | end 101 | 102 | entry = parent 103 | end 104 | 105 | return "" 106 | end 107 | 108 | local function process_images(str) 109 | return str:gsub("]+>", function(img_tag) 110 | local alt = img_tag:match("alt=\"([^\"]*)\"") 111 | local src_pattern = "src=\"([^\"]+)\"" 112 | local src = img_tag:match(src_pattern) 113 | 114 | local processed_img_tag = img_tag:gsub(src_pattern, function(s) 115 | -- we don't compress/process other image formats 116 | if utils.starts_with(s, "http") then 117 | return "src=\"" .. s .. "\"" 118 | elseif (not (utils.ends_with(s, "jpg") or utils.ends_with(s, "jpeg") or utils.ends_with(s, "png"))) then 119 | return "src=\"/" .. MEDIA_DIR_NAME .. "/" .. s .. "\"" 120 | else 121 | -- we store attachments in this directory 122 | s = MEDIA_DIR_NAME .. "/" .. s 123 | end 124 | 125 | local parts = utils.split(s, ".") 126 | 127 | -- if we've hard-specified one of our resolutions, don't append it 128 | if not (utils.ends_with(parts[1], "360") or utils.ends_with(parts[1], "720")) then 129 | s = parts[1] .. "-720." .. parts[2] 130 | end 131 | 132 | table.insert(media_paths, s) 133 | 134 | return "loading=\"lazy\" src=\"" .. s .. "\"" 135 | end) 136 | return 137 | "
" .. processed_img_tag .. "
" .. 138 | alt .. "
" 139 | end) 140 | end 141 | 142 | local function process_internal_links(string, entry, entries) 143 | return string:gsub("[^!]%[%[[^%]]+%]%]", function(match) 144 | local parts = utils.split(match:sub(4, -3), "|") 145 | local linked_name = parts[1] 146 | local display_name = parts[2] or linked_name 147 | local e = utils.get_key_case_insensitive(entries, linked_name) 148 | if e == nil then 149 | print("Warning, linked entry \"" .. linked_name .. "\" not found when rendering \"" .. entry.name .. "\"") 150 | return "{" .. display_name .. "}" 151 | end 152 | 153 | return match:sub(1, 1) .. "{" .. display_name .. "}" 154 | end) 155 | end 156 | 157 | local function render_body(entry, entries) 158 | return process_images(process_internal_links(sub_entry_fields("

{{EntryName}}

" .. 159 | (entry.date ~= nil and 160 | "
last updated {{EntryDate}}
" or 161 | "") .. "{{EntryBodyHtml}}", entry), entry, 162 | entries)) 163 | end 164 | 165 | local function render_entry(entry, entries) 166 | local html = string.format( 167 | "%s
%s
%s

Compiled %s

%s", 168 | render_head(entry), render_nav(entry, entries), render_body(entry, entries), utils.today(), render_footer()) 169 | utils.write_file(SITE_DIR .. "/" .. entry.dest_file_name, html) 170 | end 171 | 172 | local function render_rss(rss_entries) 173 | local rss_template = utils.read_file("templates/feed.tpl.rss") 174 | local item_template = utils.read_file("templates/item.tpl.rss") 175 | local items_str = "" 176 | for _, e in make_sorted_entry_iterator(rss_entries) do 177 | local rss_date = utils.rss_date(e.date) 178 | items_str = items_str .. 179 | sub_entry_fields(item_template, e):gsub("{{RSSDate}}", rss_date) 180 | :gsub("src=\"img", "src=\"https://mrshll.com/img"):gsub("%%", "%%%%") -- this escapes %, which is lua's escape char, otherwise the final gsub fails 181 | end 182 | utils.write_file(SITE_DIR .. "/feed.rss", rss_template:gsub("{{Items}}", items_str)) 183 | end 184 | 185 | -- expects an html body and will embed files with the ![[name]] syntax 186 | local function process_embeds(body_html, entries) 187 | return body_html:gsub("!%[%[([^%]]+)%]%]", function(embedded_entry_name) 188 | for _, entry in pairs(entries) do 189 | if entry.name == embedded_entry_name then 190 | return "

" .. 191 | entry.name .. 192 | "

#" .. markdown(entry.body_raw) .. "
" 193 | end 194 | end 195 | end) 196 | end 197 | 198 | local entries = {} 199 | local file_paths = utils.list_files(DATA_DIR, DATA_EXT) 200 | for _, file_path in pairs(file_paths) do 201 | -- split on slash to get path fragments 202 | local parts = utils.split(file_path, "/") 203 | 204 | for _, key in pairs(parts) do 205 | if utils.starts_with(key, '_') then 206 | goto continue 207 | end 208 | end 209 | 210 | -- directory scheme is /entry-name or [/parent's parent]/parent/entry-name (recursive) 211 | local parent_name = parts[#parts - 1] or SITE_NAME 212 | 213 | -- remove the file extension 214 | local name = parts[#parts]:sub(0, -1 * #DATA_EXT - 1) 215 | local dest_file_name = utils.slugify(name) .. ".html" 216 | 217 | local is_index = name == INDEX_NAME 218 | if is_index then 219 | name = parent_name 220 | if parent_name == SITE_NAME then 221 | -- root node 222 | dest_file_name = "index.html" 223 | else 224 | -- subtree root nodes 225 | dest_file_name = name .. ".html" 226 | parent_name = parts[#parts - 2] or SITE_NAME 227 | end 228 | end 229 | 230 | local body = utils.read_file(DATA_DIR .. file_path) 231 | 232 | local date 233 | local date_start, date_end = body:find("%d%d%d%d%-%d%d%-%d%d") 234 | if date_start == 1 then 235 | date = body:sub(date_start, date_end) 236 | body = body:sub(date_end + 1) 237 | end 238 | 239 | local html = markdown(body) 240 | entries[name] = { 241 | name = name, 242 | src_path = file_path, 243 | dest_file_name = dest_file_name, 244 | parent_name = parent_name, 245 | body_raw = body, 246 | body_html = html, 247 | date = date, 248 | is_index = is_index 249 | } 250 | 251 | ::continue:: 252 | end 253 | 254 | local i = 0 255 | for _, entry in pairs(entries) do 256 | entry.body_html = process_embeds(entry.body_html, entries) 257 | render_entry(entry, entries) 258 | i = i + 1 259 | end 260 | 261 | local rss_entries = {} 262 | for _, e in pairs(entries) do 263 | if (e.parent_name == "Writing" or e.parent_name == 'Log') and e.date ~= nil then 264 | table.insert(rss_entries, e) 265 | end 266 | end 267 | render_rss(rss_entries) 268 | 269 | for _, media_path in pairs(media_paths) do 270 | local path = SITE_DIR .. "/" .. media_path 271 | if not utils.file_exists(path) then 272 | print("referenced media not found", path, " ... attempting to process") 273 | utils.process_image(DATA_DIR, SITE_DIR, path:gsub("-720", ""):gsub("-360", ""):gsub(SITE_DIR, DATA_DIR)) 274 | end 275 | end 276 | 277 | print("Rendered " .. i .. " entries.") 278 | -------------------------------------------------------------------------------- /src/markdown.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local utils = require "utils" 4 | 5 | ---------------------------------------------------------------------- 6 | -- Utility functions 7 | ---------------------------------------------------------------------- 8 | local unpack = table.unpack or unpack 9 | 10 | -- Returns the result of mapping the values in table t through the function f 11 | local function map(t, f) 12 | local out = {} 13 | for k, v in pairs(t) do 14 | out[k] = f(v, k) 15 | end 16 | return out 17 | end 18 | 19 | -- Functional style if statement. (NOTE: no short circuit evaluation) 20 | local function iff(t, a, b) 21 | if t then 22 | return a 23 | else 24 | return b 25 | end 26 | end 27 | 28 | -- Splits the text into an array of separate lines. 29 | local function split(text, sep) 30 | sep = sep or "\n" 31 | local lines = {} 32 | local pos = 1 33 | while true do 34 | local b, e = text:find(sep, pos) 35 | if not b then 36 | table.insert(lines, text:sub(pos)) 37 | break 38 | end 39 | table.insert(lines, text:sub(pos, b - 1)) 40 | pos = e + 1 41 | end 42 | return lines 43 | end 44 | 45 | -- Converts tabs to spaces 46 | local function detab(text) 47 | local tab_width = 4 48 | local function rep(match) 49 | local spaces = -match:len() 50 | while spaces < 1 do 51 | spaces = spaces + tab_width 52 | end 53 | return match .. string.rep(" ", spaces) 54 | end 55 | 56 | text = text:gsub("([^\n]-)\t", rep) 57 | return text 58 | end 59 | 60 | -- Applies string.find for every pattern in the list and returns the first match 61 | local function find_first(s, patterns, index) 62 | local res = {} 63 | for _, p in ipairs(patterns) do 64 | local match = { s:find(p, index) } 65 | if #match > 0 and (#res == 0 or match[1] < res[1]) then 66 | res = match 67 | end 68 | end 69 | return unpack(res) 70 | end 71 | 72 | -- If a replacement array is specified, the range [start, stop] in the array is replaced 73 | -- with the replacement array and the resulting array is returned. Without a replacement 74 | -- array the section of the array between start and stop is returned. 75 | local function splice(array, start, stop, replacement) 76 | if replacement then 77 | local n = stop - start + 1 78 | while n > 0 do 79 | table.remove(array, start) 80 | n = n - 1 81 | end 82 | for _, v in ipairs(replacement) do 83 | table.insert(array, start, v) 84 | end 85 | return array 86 | else 87 | local res = {} 88 | for i = start, stop do 89 | table.insert(res, array[i]) 90 | end 91 | return res 92 | end 93 | end 94 | 95 | -- Outdents the text one step. 96 | local function outdent(text) 97 | text = "\n" .. text 98 | text = text:gsub("\n ? ? ?", "\n") 99 | text = text:sub(2) 100 | return text 101 | end 102 | 103 | -- Indents the text one step. 104 | local function indent(text) 105 | text = text:gsub("\n", "\n ") 106 | return text 107 | end 108 | 109 | -- Does a simple tokenization of html data. Returns the data as a list of tokens. 110 | -- Each token is a table with a type field (which is either "tag" or "text") and 111 | -- a text field (which contains the original token data). 112 | local function tokenize_html(html) 113 | local tokens = {} 114 | local pos = 1 115 | while true do 116 | local start = find_first(html, { "", start) 134 | elseif html:match("^<%?", start) then 135 | _, stop = html:find("?>", start) 136 | else 137 | _, stop = html:find("%b<>", start) 138 | end 139 | if not stop then 140 | -- error("Could not match html tag " .. html:sub(start,start+30)) 141 | table.insert(tokens, { 142 | type = "text", 143 | text = html:sub(start, start) 144 | }) 145 | pos = start + 1 146 | else 147 | table.insert(tokens, { 148 | type = "tag", 149 | text = html:sub(start, stop) 150 | }) 151 | pos = stop + 1 152 | end 153 | end 154 | return tokens 155 | end 156 | 157 | ---------------------------------------------------------------------- 158 | -- Hash 159 | ---------------------------------------------------------------------- 160 | 161 | -- This is used to "hash" data into alphanumeric strings that are unique 162 | -- in the document. (Note that this is not cryptographic hash, the hash 163 | -- function is not one-way.) The hash procedure is used to protect parts 164 | -- of the document from further processing. 165 | 166 | local HASH = { 167 | -- Has the hash been inited. 168 | inited = false, 169 | 170 | -- The unique string prepended to all hash values. This is to ensure 171 | -- that hash values do not accidently coincide with an actual existing 172 | -- string in the document. 173 | identifier = "", 174 | 175 | -- Counter that counts up for each new hash instance. 176 | counter = 0, 177 | 178 | -- Hash table. 179 | table = {} 180 | } 181 | 182 | -- Inits hashing. Creates a hash_identifier that doesn't occur anywhere 183 | -- in the text. 184 | local function init_hash(text) 185 | HASH.inited = true 186 | HASH.identifier = "" 187 | HASH.counter = 0 188 | HASH.table = {} 189 | 190 | local s = "HASH" 191 | local counter = 0 192 | local id 193 | while true do 194 | id = s .. counter 195 | if not text:find(id, 1, true) then 196 | break 197 | end 198 | counter = counter + 1 199 | end 200 | HASH.identifier = id 201 | end 202 | 203 | -- Returns the hashed value for s. 204 | local function hash(s) 205 | assert(HASH.inited) 206 | if not HASH.table[s] then 207 | HASH.counter = HASH.counter + 1 208 | local id = HASH.identifier .. HASH.counter .. "X" 209 | HASH.table[s] = id 210 | end 211 | return HASH.table[s] 212 | end 213 | 214 | ---------------------------------------------------------------------- 215 | -- Protection 216 | ---------------------------------------------------------------------- 217 | 218 | -- The protection module is used to "protect" parts of a document 219 | -- so that they are not modified by subsequent processing steps. 220 | -- Protected parts are saved in a table for later unprotection 221 | 222 | -- Protection data 223 | local PD = { 224 | -- Saved blocks that have been converted 225 | blocks = {}, 226 | 227 | -- Block level tags that will be protected 228 | tags = { "p", "div", "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "pre", "table", "dl", "ol", "ul", "script", 229 | "noscript", "form", "fieldset", "iframe", "math", "ins", "del" } 230 | } 231 | 232 | -- Pattern for matching a block tag that begins and ends in the leftmost 233 | -- column and may contain indented subtags, i.e. 234 | --
235 | -- A nested block. 236 | --
237 | -- Nested data. 238 | --
239 | --
240 | local function block_pattern(tag) 241 | return "\n<" .. tag .. ".-\n[ \t]*\n" 242 | end 243 | 244 | -- Pattern for matching a block tag that begins and ends with a newline 245 | local function line_pattern(tag) 246 | return "\n<" .. tag .. ".-[ \t]*\n" 247 | end 248 | 249 | -- Protects the range of characters from start to stop in the text and 250 | -- returns the protected string. 251 | local function protect_range(text, start, stop) 252 | local s = text:sub(start, stop) 253 | local h = hash(s) 254 | PD.blocks[h] = s 255 | text = text:sub(1, start) .. h .. text:sub(stop) 256 | return text 257 | end 258 | 259 | -- Protect every part of the text that matches any of the patterns. The first 260 | -- matching pattern is protected first, etc. 261 | local function protect_matches(text, patterns) 262 | while true do 263 | local start, stop = find_first(text, patterns) 264 | if not start then 265 | break 266 | end 267 | text = protect_range(text, start, stop) 268 | end 269 | return text 270 | end 271 | 272 | -- Protects blocklevel tags in the specified text 273 | local function protect(text) 274 | -- First protect potentially nested block tags 275 | text = protect_matches(text, map(PD.tags, block_pattern)) 276 | -- Then protect block tags at the line level. 277 | text = protect_matches(text, map(PD.tags, line_pattern)) 278 | -- Protect
and comment tags 279 | text = protect_matches(text, { "\n]->[ \t]*\n" }) 280 | text = protect_matches(text, { "\n[ \t]*\n" }) 281 | return text 282 | end 283 | 284 | -- Returns true if the string s is a hash resulting from protection 285 | local function is_protected(s) 286 | return PD.blocks[s] 287 | end 288 | 289 | -- Unprotects the specified text by expanding all the nonces 290 | local function unprotect(text) 291 | for k, v in pairs(PD.blocks) do 292 | v = v:gsub("%%", "%%%%") 293 | text = text:gsub(k, v) 294 | end 295 | return text 296 | end 297 | 298 | ---------------------------------------------------------------------- 299 | -- Block transform 300 | ---------------------------------------------------------------------- 301 | 302 | -- The block transform functions transform the text on the block level. 303 | -- They work with the text as an array of lines rather than as individual 304 | -- characters. 305 | 306 | -- Returns true if the line is a ruler of (char) characters. 307 | -- The line must contain at least three char characters and contain only spaces and 308 | -- char characters. 309 | local function is_ruler_of(line, char) 310 | if not line:match("^[ %" .. char .. "]*$") then 311 | return false 312 | end 313 | if not line:match("%" .. char .. ".*%" .. char .. ".*%" .. char) then 314 | return false 315 | end 316 | return true 317 | end 318 | 319 | -- Identifies the block level formatting present in the line 320 | local function classify(line) 321 | local info = { 322 | line = line, 323 | text = line 324 | } 325 | 326 | if line:match("^ ") then 327 | info.type = "indented" 328 | info.outdented = line:sub(5) 329 | return info 330 | end 331 | 332 | if line:match("^```.*") then 333 | info.type = 'codeblock' 334 | info.language = line:sub(4) 335 | info.text = "" 336 | return info 337 | end 338 | 339 | for _, c in ipairs({ '*', '-', '_', '=' }) do 340 | if is_ruler_of(line, c) then 341 | info.type = "ruler" 342 | info.ruler_char = c 343 | return info 344 | end 345 | end 346 | 347 | if line == "" then 348 | info.type = "blank" 349 | return info 350 | end 351 | 352 | if line:match("^(#+)[ \t]*(.-)[ \t]*#*[ \t]*$") then 353 | local m1, m2 = line:match("^(#+)[ \t]*(.-)[ \t]*#*[ \t]*$") 354 | info.type = "header" 355 | info.level = m1:len() 356 | info.text = m2 357 | return info 358 | end 359 | 360 | if line:match("^ ? ? ?(%d+)%.[ \t]+(.+)") then 361 | local number, text = line:match("^ ? ? ?(%d+)%.[ \t]+(.+)") 362 | info.type = "list_item" 363 | info.list_type = "numeric" 364 | info.number = 0 + number 365 | info.text = text 366 | return info 367 | end 368 | 369 | if line:match("^ ? ? ?([%*%+%-])[ \t]+(.+)") then 370 | local bullet, text = line:match("^ ? ? ?([%*%+%-])[ \t]+(.+)") 371 | info.type = "list_item" 372 | info.list_type = "bullet" 373 | info.bullet = bullet 374 | info.text = text 375 | return info 376 | end 377 | 378 | if line:match("^>[ \t]?(.*)") then 379 | info.type = "blockquote" 380 | info.text = line:match("^>[ \t]?(.*)") 381 | return info 382 | end 383 | 384 | if is_protected(line) then 385 | info.type = "raw" 386 | info.html = unprotect(line) 387 | return info 388 | end 389 | 390 | info.type = "normal" 391 | return info 392 | end 393 | 394 | -- Find headers constisting of a normal line followed by a ruler and converts them to 395 | -- header entries. 396 | local function headers(array) 397 | local i = 1 398 | while i <= #array - 1 do 399 | if array[i].type == "normal" and array[i + 1].type == "ruler" and 400 | (array[i + 1].ruler_char == "-" or array[i + 1].ruler_char == "=") then 401 | local info = { 402 | line = array[i].line 403 | } 404 | info.text = info.line 405 | info.type = "header" 406 | info.level = iff(array[i + 1].ruler_char == "=", 1, 2) 407 | table.remove(array, i + 1) 408 | array[i] = info 409 | end 410 | i = i + 1 411 | end 412 | return array 413 | end 414 | 415 | -- Forward declarations 416 | local block_transform, span_transform, encode_code 417 | 418 | -- Convert lines to html code 419 | local function blocks_to_html(lines, no_paragraphs) 420 | local out = {} 421 | local i = 1 422 | while i <= #lines do 423 | local line = lines[i] 424 | if line.type == "ruler" then 425 | table.insert(out, "
") 426 | elseif line.type == "raw" then 427 | table.insert(out, line.html) 428 | elseif line.type == "normal" then 429 | local s = line.line 430 | 431 | while i + 1 <= #lines and lines[i + 1].type == "normal" do 432 | i = i + 1 433 | s = s .. "\n" .. lines[i].line 434 | end 435 | 436 | if no_paragraphs then 437 | table.insert(out, span_transform(s)) 438 | else 439 | table.insert(out, "

" .. span_transform(s) .. "

") 440 | end 441 | elseif line.type == "header" then 442 | local s = "" .. span_transform(line.text) .. "" 443 | table.insert(out, s) 444 | else 445 | table.insert(out, line.line) 446 | end 447 | i = i + 1 448 | end 449 | return out 450 | end 451 | 452 | -- Find list blocks and convert them to protected data blocks 453 | local function lists(array, sublist) 454 | local function process_list(arr) 455 | local function any_blanks(arr) 456 | for i = 1, #arr do 457 | if arr[i].type == "blank" then 458 | return true 459 | end 460 | end 461 | return false 462 | end 463 | 464 | local function split_list_items(arr) 465 | local acc = { arr[1] } 466 | local res = {} 467 | for i = 2, #arr do 468 | if arr[i].type == "list_item" then 469 | table.insert(res, acc) 470 | acc = { arr[i] } 471 | else 472 | table.insert(acc, arr[i]) 473 | end 474 | end 475 | table.insert(res, acc) 476 | return res 477 | end 478 | 479 | local function process_list_item(lines, block) 480 | while lines[#lines].type == "blank" do 481 | table.remove(lines) 482 | end 483 | 484 | local itemtext = lines[1].text 485 | for i = 2, #lines do 486 | itemtext = itemtext .. "\n" .. outdent(lines[i].line) 487 | end 488 | if block then 489 | itemtext = block_transform(itemtext, true) 490 | if not itemtext:find("
") then
 491 |                     itemtext = indent(itemtext)
 492 |                 end
 493 |                 return "    
  • " .. itemtext .. "
  • " 494 | else 495 | local lines = split(itemtext) 496 | lines = map(lines, classify) 497 | lines = lists(lines, true) 498 | lines = blocks_to_html(lines, true) 499 | itemtext = table.concat(lines, "\n") 500 | if not itemtext:find("
    ") then
     501 |                     itemtext = indent(itemtext)
     502 |                 end
     503 |                 return "    
  • " .. itemtext .. "
  • " 504 | end 505 | end 506 | 507 | local block_list = any_blanks(arr) 508 | local items = split_list_items(arr) 509 | local out = "" 510 | for _, item in ipairs(items) do 511 | out = out .. process_list_item(item, block_list) .. "\n" 512 | end 513 | if arr[1].list_type == "numeric" then 514 | return "
      \n" .. out .. "
    " 515 | else 516 | return "
      \n" .. out .. "
    " 517 | end 518 | end 519 | 520 | -- Finds the range of lines composing the first list in the array. A list 521 | -- starts with (^ list_item) or (blank list_item) and ends with 522 | -- (blank* $) or (blank normal). 523 | -- 524 | -- A sublist can start with just (list_item) does not need a blank... 525 | local function find_list(array, sublist) 526 | local function find_list_start(array, sublist) 527 | if array[1].type == "list_item" then 528 | return 1 529 | end 530 | if sublist then 531 | for i = 1, #array do 532 | if array[i].type == "list_item" then 533 | return i 534 | end 535 | end 536 | else 537 | for i = 1, #array - 1 do 538 | if array[i].type == "list_item" then 539 | return i 540 | end 541 | end 542 | end 543 | return nil 544 | end 545 | 546 | local function find_list_end(array, start) 547 | local pos = #array 548 | for i = start, #array - 1 do 549 | if array[i].type == "blank" and array[i + 1].type ~= "list_item" and array[i + 1].type ~= "indented" and 550 | array[i + 1].type ~= "blank" then 551 | pos = i - 1 552 | break 553 | end 554 | end 555 | while pos > start and array[pos].type == "blank" do 556 | pos = pos - 1 557 | end 558 | return pos 559 | end 560 | 561 | local start = find_list_start(array, sublist) 562 | if not start then 563 | return nil 564 | end 565 | return start, find_list_end(array, start) 566 | end 567 | 568 | while true do 569 | local start, stop = find_list(array, sublist) 570 | if not start then 571 | break 572 | end 573 | local text = process_list(splice(array, start, stop)) 574 | local info = { 575 | line = text, 576 | type = "raw", 577 | html = text 578 | } 579 | array = splice(array, start, stop, { info }) 580 | end 581 | 582 | -- Convert any remaining list items to normal 583 | for _, line in ipairs(array) do 584 | if line.type == "list_item" then 585 | line.type = "normal" 586 | end 587 | end 588 | 589 | return array 590 | end 591 | 592 | -- Find and convert blockquote markers. 593 | local function blockquotes(lines) 594 | local function find_blockquote(lines) 595 | local start 596 | for i, line in ipairs(lines) do 597 | if line.type == "blockquote" then 598 | start = i 599 | break 600 | end 601 | end 602 | if not start then 603 | return nil 604 | end 605 | 606 | local stop = #lines 607 | for i = start + 1, #lines do 608 | if lines[i].type == "blank" or lines[i].type == "blockquote" then 609 | elseif lines[i].type == "normal" then 610 | if lines[i - 1].type == "blank" then 611 | stop = i - 1 612 | break 613 | end 614 | else 615 | stop = i - 1 616 | break 617 | end 618 | end 619 | while lines[stop].type == "blank" do 620 | stop = stop - 1 621 | end 622 | return start, stop 623 | end 624 | 625 | local function process_blockquote(lines) 626 | local raw = lines[1].text 627 | for i = 2, #lines do 628 | raw = raw .. "\n" .. lines[i].text 629 | end 630 | local bt = block_transform(raw) 631 | if not bt:find("
    ") then
     632 |             bt = indent(bt)
     633 |         end
     634 |         return "
    \n " .. bt .. "\n
    " 635 | end 636 | 637 | while true do 638 | local start, stop = find_blockquote(lines) 639 | if not start then 640 | break 641 | end 642 | local text = process_blockquote(splice(lines, start, stop)) 643 | local info = { 644 | line = text, 645 | type = "raw", 646 | html = text 647 | } 648 | lines = splice(lines, start, stop, { info }) 649 | end 650 | return lines 651 | end 652 | 653 | -- Find and convert codeblocks. 654 | local function codeblocks(lines) 655 | local function find_codeblock(lines) 656 | local start 657 | for i, line in ipairs(lines) do 658 | if line.type == "indented" or line.type == "codeblock" then 659 | start = i 660 | break 661 | end 662 | end 663 | if not start then 664 | return nil 665 | end 666 | 667 | local stop = #lines 668 | for i = start + 1, #lines do 669 | if lines[i].type == "codeblock" then 670 | stop = i 671 | break 672 | end 673 | end 674 | while lines[stop].type == "blank" do 675 | stop = stop - 1 676 | end 677 | return start, stop 678 | end 679 | 680 | local function process_codeblock(lines) 681 | local raw = detab(encode_code(lines[1].text or "")) 682 | for i = 2, #lines do 683 | raw = raw .. "\n" .. detab(encode_code(lines[i].text or "")) 684 | end 685 | return "
    " .. raw .. "\n
    " 686 | end 687 | 688 | while true do 689 | local start, stop = find_codeblock(lines) 690 | if not start then 691 | break 692 | end 693 | local text = process_codeblock(splice(lines, start, stop)) 694 | local info = { 695 | line = text, 696 | type = "raw", 697 | html = text 698 | } 699 | lines = splice(lines, start, stop, { info }) 700 | end 701 | return lines 702 | end 703 | 704 | -- Perform all the block level transforms 705 | function block_transform(text, sublist) 706 | local lines = split(text) 707 | lines = map(lines, classify) 708 | lines = headers(lines) 709 | lines = lists(lines, sublist) 710 | lines = codeblocks(lines) 711 | lines = blockquotes(lines) 712 | lines = blocks_to_html(lines) 713 | local text = table.concat(lines, "\n") 714 | return text 715 | end 716 | 717 | ---------------------------------------------------------------------- 718 | -- Span transform 719 | ---------------------------------------------------------------------- 720 | 721 | -- Functions for transforming the text at the span level. 722 | 723 | -- These characters may need to be escaped because they have a special 724 | -- meaning in markdown. 725 | local escape_chars = "'\\`*_{}[]()>#+-.!'" 726 | local escape_table = {} 727 | 728 | local function init_escape_table() 729 | escape_table = {} 730 | for i = 1, #escape_chars do 731 | local c = escape_chars:sub(i, i) 732 | escape_table[c] = hash(c) 733 | end 734 | end 735 | 736 | -- Adds a new escape to the escape table. 737 | local function add_escape(text) 738 | if not escape_table[text] then 739 | escape_table[text] = hash(text) 740 | end 741 | return escape_table[text] 742 | end 743 | 744 | -- Encode backspace-escaped characters in the markdown source. 745 | local function encode_backslash_escapes(t) 746 | for i = 1, escape_chars:len() do 747 | local c = escape_chars:sub(i, i) 748 | t = t:gsub("\\%" .. c, escape_table[c]) 749 | end 750 | return t 751 | end 752 | 753 | -- Escape characters that should not be disturbed by markdown. 754 | local function escape_special_chars(text) 755 | local tokens = tokenize_html(text) 756 | 757 | local out = "" 758 | for _, token in ipairs(tokens) do 759 | local t = token.text 760 | if token.type == "tag" then 761 | -- In tags, encode * and _ so they don't conflict with their use in markdown. 762 | t = t:gsub("%*", escape_table["*"]) 763 | t = t:gsub("%_", escape_table["_"]) 764 | else 765 | t = encode_backslash_escapes(t) 766 | end 767 | out = out .. t 768 | end 769 | return out 770 | end 771 | 772 | -- Unescape characters that have been encoded. 773 | local function unescape_special_chars(t) 774 | local tin = t 775 | for k, v in pairs(escape_table) do 776 | k = k:gsub("%%", "%%%%") 777 | t = t:gsub(v, k) 778 | end 779 | if t ~= tin then 780 | t = unescape_special_chars(t) 781 | end 782 | return t 783 | end 784 | 785 | -- Encode/escape certain characters inside Markdown code runs. 786 | -- The point is that in code, these characters are literals, 787 | -- and lose their special Markdown meanings. 788 | function encode_code(s) 789 | s = s:gsub("%&", "&") 790 | s = s:gsub("<", "<") 791 | s = s:gsub(">", ">") 792 | for k, v in pairs(escape_table) do 793 | s = s:gsub("%" .. k, v) 794 | end 795 | return s 796 | end 797 | 798 | -- Handle backtick blocks. 799 | local function code_spans(s) 800 | s = s:gsub("\\\\", escape_table["\\"]) 801 | s = s:gsub("\\`", escape_table["`"]) 802 | 803 | local pos = 1 804 | while true do 805 | local start, stop = s:find("`+", pos) 806 | if not start then 807 | return s 808 | end 809 | local count = stop - start + 1 810 | -- Find a matching numbert of backticks 811 | local estart, estop = s:find(string.rep("`", count), stop + 1) 812 | local brstart = s:find("\n", stop + 1) 813 | if estart and (not brstart or estart < brstart) then 814 | local code = s:sub(stop + 1, estart - 1) 815 | code = code:gsub("^[ \t]+", "") 816 | code = code:gsub("[ \t]+$", "") 817 | code = code:gsub(escape_table["\\"], escape_table["\\"] .. escape_table["\\"]) 818 | code = code:gsub(escape_table["`"], escape_table["\\"] .. escape_table["`"]) 819 | code = "" .. encode_code(code) .. "" 820 | code = add_escape(code) 821 | s = s:sub(1, start - 1) .. code .. s:sub(estop + 1) 822 | pos = start + code:len() 823 | else 824 | pos = stop + 1 825 | end 826 | end 827 | end 828 | 829 | -- Encode alt text... enodes &, and ". 830 | local function encode_alt(s) 831 | if not s then 832 | return s 833 | end 834 | s = s:gsub('&', '&') 835 | s = s:gsub('"', '"') 836 | s = s:gsub('<', '<') 837 | return s 838 | end 839 | 840 | -- Handle image references 841 | local function images(text) 842 | local function inline_link(alt, link) 843 | alt = encode_alt(alt:match("%b[]"):sub(2, -2)) 844 | local url, title = link:match("%(?[ \t]*['\"](.+)['\"]") 845 | url = url or link:match("%(?%)") 846 | url = encode_alt(url) 847 | title = encode_alt(title) 848 | if title then 849 | return add_escape('' .. alt .. '') 850 | else 851 | return add_escape('' .. alt .. '') 852 | end 853 | end 854 | 855 | text = text:gsub("!(%b[])(%b())", inline_link) 856 | return text 857 | end 858 | 859 | -- Handle anchor references 860 | local function anchors(text) 861 | local function inline_link(text, link) 862 | text = text:match("%b[]"):sub(2, -2) 863 | local url, title = link:match("%(?[ \t]*['\"](.+)['\"]") 864 | title = encode_alt(title) 865 | url = url or link:match("%(?%)") or "" 866 | url = encode_alt(url) 867 | if title then 868 | return add_escape("") .. text .. "" 869 | else 870 | return add_escape("") .. text .. add_escape("") 871 | end 872 | end 873 | 874 | text = text:gsub("(%b[])(%b())", inline_link) 875 | return text 876 | end 877 | 878 | -- Handle auto links, i.e. . 879 | local function auto_links(text) 880 | local function link(s) 881 | return add_escape("") .. s .. "" 882 | end 883 | 884 | -- Encode chars as a mix of dec and hex entitites to (perhaps) fool 885 | -- spambots. 886 | local function encode_email_address(s) 887 | -- Use a deterministic encoding to make unit testing possible. 888 | -- Code 45% hex, 45% dec, 10% plain. 889 | local hex = { 890 | code = function(c) 891 | return "&#x" .. string.format("%x", c:byte()) .. ";" 892 | end, 893 | count = 1, 894 | rate = 0.45 895 | } 896 | local dec = { 897 | code = function(c) 898 | return "&#" .. c:byte() .. ";" 899 | end, 900 | count = 0, 901 | rate = 0.45 902 | } 903 | local plain = { 904 | code = function(c) 905 | return c 906 | end, 907 | count = 0, 908 | rate = 0.1 909 | } 910 | local codes = { hex, dec, plain } 911 | local function swap(t, k1, k2) 912 | local temp = t[k2] 913 | t[k2] = t[k1] 914 | t[k1] = temp 915 | end 916 | 917 | local out = "" 918 | for i = 1, s:len() do 919 | for _, code in ipairs(codes) do 920 | code.count = code.count + code.rate 921 | end 922 | if codes[1].count < codes[2].count then 923 | swap(codes, 1, 2) 924 | end 925 | if codes[2].count < codes[3].count then 926 | swap(codes, 2, 3) 927 | end 928 | if codes[1].count < codes[2].count then 929 | swap(codes, 1, 2) 930 | end 931 | 932 | local code = codes[1] 933 | local c = s:sub(i, i) 934 | -- Force encoding of "@" to make email address more invisible. 935 | if c == "@" and code == plain then 936 | code = codes[2] 937 | end 938 | out = out .. code.code(c) 939 | code.count = code.count - 1 940 | end 941 | return out 942 | end 943 | 944 | local function mail(s) 945 | s = unescape_special_chars(s) 946 | local address = encode_email_address("mailto:" .. s) 947 | local text = encode_email_address(s) 948 | return add_escape("") .. text .. "" 949 | end 950 | 951 | -- links 952 | text = text:gsub("<(https?:[^'\">%s]+)>", link) 953 | text = text:gsub("<(ftp:[^'\">%s]+)>", link) 954 | 955 | -- mail 956 | text = text:gsub("%s]+)>", mail) 957 | text = text:gsub("<([-.%w]+%@[-.%w]+)>", mail) 958 | return text 959 | end 960 | 961 | -- Encode free standing amps (&) and angles (<)... note that this does not 962 | -- encode free >. 963 | local function amps_and_angles(s) 964 | -- encode amps not part of &..; expression 965 | local pos = 1 966 | while true do 967 | local amp = s:find("&", pos) 968 | if not amp then 969 | break 970 | end 971 | local semi = s:find(";", amp + 1) 972 | local stop = s:find("[ \t\n&]", amp + 1) 973 | if not semi or (stop and stop < semi) or (semi - amp) > 15 then 974 | s = s:sub(1, amp - 1) .. "&" .. s:sub(amp + 1) 975 | pos = amp + 1 976 | else 977 | pos = amp + 1 978 | end 979 | end 980 | 981 | -- encode naked <'s 982 | s = s:gsub("<([^a-zA-Z/?$!])", "<%1") 983 | s = s:gsub("<$", "<") 984 | 985 | -- what about >, nothing done in the original markdown source to handle them 986 | return s 987 | end 988 | 989 | -- Handles emphasis markers (* and _) in the text. 990 | local function emphasis(text) 991 | for _, s in ipairs { "%*%*", "%_%_" } do 992 | text = text:gsub(s .. "([^%s][%*%_]?)" .. s, "%1") 993 | text = text:gsub(s .. "([^%s][^<>]-[^%s][%*%_]?)" .. s, "%1") 994 | end 995 | for _, s in ipairs { "%*", "%_" } do 996 | text = text:gsub(s .. "([^%s_])" .. s, "%1") 997 | text = text:gsub(s .. "([^%s_])" .. s, "%1") 998 | text = text:gsub(s .. "([^%s_][^<>_]-[^%s_])" .. s, "%1") 999 | text = text:gsub(s .. "([^<>_]-[^<>_]-[^<>_]-)" .. s, "%1") 1000 | end 1001 | return text 1002 | end 1003 | 1004 | -- Handles line break markers in the text. 1005 | local function line_breaks(text) 1006 | return text:gsub(" +\n", "
    \n") 1007 | end 1008 | 1009 | local function footnotes(text) 1010 | return text:gsub("%[%^(%d+)%]: ([^\n]+)", 1011 | "
    %1. %2
    "):gsub("%[%^(%d+)%]", 1012 | "[%1]") 1013 | end 1014 | 1015 | -- Perform all span level transforms. 1016 | function span_transform(text) 1017 | text = code_spans(text) 1018 | text = escape_special_chars(text) 1019 | text = images(text) 1020 | text = anchors(text) 1021 | text = auto_links(text) 1022 | text = amps_and_angles(text) 1023 | text = emphasis(text) 1024 | text = line_breaks(text) 1025 | text = footnotes(text) 1026 | return text 1027 | end 1028 | 1029 | ---------------------------------------------------------------------- 1030 | -- Markdown 1031 | ---------------------------------------------------------------------- 1032 | 1033 | -- Cleanup the text by normalizing some possible variations to make further 1034 | -- processing easier. 1035 | local function cleanup(text) 1036 | -- Standardize line endings 1037 | text = text:gsub("\r\n", "\n") -- DOS to UNIX 1038 | text = text:gsub("\r", "\n") -- Mac to UNIX 1039 | 1040 | -- Convert all tabs to spaces 1041 | text = detab(text) 1042 | 1043 | -- Strip lines with only spaces and tabs 1044 | while true do 1045 | local subs 1046 | text, subs = text:gsub("\n[ \t]+\n", "\n\n") 1047 | if subs == 0 then 1048 | break 1049 | end 1050 | end 1051 | 1052 | return "\n" .. text .. "\n" 1053 | end 1054 | 1055 | -- Main markdown processing function 1056 | local function markdown(text) 1057 | init_hash(text) 1058 | init_escape_table() 1059 | 1060 | text = cleanup(text) 1061 | text = protect(text) 1062 | text = block_transform(text) 1063 | text = unescape_special_chars(text) 1064 | return text 1065 | end 1066 | 1067 | ---------------------------------------------------------------------- 1068 | -- End of module 1069 | ---------------------------------------------------------------------- 1070 | 1071 | return markdown 1072 | -------------------------------------------------------------------------------- /static/highlight.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Highlight.js v11.9.0 (git: b7ec4bfafc) 3 | (c) 2006-2024 undefined and other contributors 4 | License: BSD-3-Clause 5 | */ 6 | var hljs=function(){"use strict";function e(t){ 7 | return t instanceof Map?t.clear=t.delete=t.set=()=>{ 8 | throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{ 9 | throw Error("set is read-only") 10 | }),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{ 11 | const i=t[n],s=typeof i;"object"!==s&&"function"!==s||Object.isFrozen(i)||e(i) 12 | })),t}class t{constructor(e){ 13 | void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} 14 | ignoreMatch(){this.isMatchIgnored=!0}}function n(e){ 15 | return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") 16 | }function i(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] 17 | ;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const s=e=>!!e.scope 18 | ;class o{constructor(e,t){ 19 | this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ 20 | this.buffer+=n(e)}openNode(e){if(!s(e))return;const t=((e,{prefix:t})=>{ 21 | if(e.startsWith("language:"))return e.replace("language:","language-") 22 | ;if(e.includes(".")){const n=e.split(".") 23 | ;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") 24 | }return`${t}${e}`})(e.scope,{prefix:this.classPrefix});this.span(t)} 25 | closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ 26 | this.buffer+=``}}const r=(e={})=>{const t={children:[]} 27 | ;return Object.assign(t,e),t};class a{constructor(){ 28 | this.rootNode=r(),this.stack=[this.rootNode]}get top(){ 29 | return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ 30 | this.top.children.push(e)}openNode(e){const t=r({scope:e}) 31 | ;this.add(t),this.stack.push(t)}closeNode(){ 32 | if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ 33 | for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} 34 | walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ 35 | return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), 36 | t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ 37 | "string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ 38 | a._collapse(e)})))}}class c extends a{constructor(e){super(),this.options=e} 39 | addText(e){""!==e&&this.add(e)}startScope(e){this.openNode(e)}endScope(){ 40 | this.closeNode()}__addSublanguage(e,t){const n=e.root 41 | ;t&&(n.scope="language:"+t),this.add(n)}toHTML(){ 42 | return new o(this,this.options).value()}finalize(){ 43 | return this.closeAllNodes(),!0}}function l(e){ 44 | return e?"string"==typeof e?e:e.source:null}function g(e){return h("(?=",e,")")} 45 | function u(e){return h("(?:",e,")*")}function d(e){return h("(?:",e,")?")} 46 | function h(...e){return e.map((e=>l(e))).join("")}function f(...e){const t=(e=>{ 47 | const t=e[e.length-1] 48 | ;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} 49 | })(e);return"("+(t.capture?"":"?:")+e.map((e=>l(e))).join("|")+")"} 50 | function p(e){return RegExp(e.toString()+"|").exec("").length-1} 51 | const b=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ 52 | ;function m(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n 53 | ;let i=l(e),s="";for(;i.length>0;){const e=b.exec(i);if(!e){s+=i;break} 54 | s+=i.substring(0,e.index), 55 | i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?s+="\\"+(Number(e[1])+t):(s+=e[0], 56 | "("===e[0]&&n++)}return s})).map((e=>`(${e})`)).join(t)} 57 | const E="[a-zA-Z]\\w*",x="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",y="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",_="\\b(0b[01]+)",O={ 58 | begin:"\\\\[\\s\\S]",relevance:0},v={scope:"string",begin:"'",end:"'", 59 | illegal:"\\n",contains:[O]},k={scope:"string",begin:'"',end:'"',illegal:"\\n", 60 | contains:[O]},N=(e,t,n={})=>{const s=i({scope:"comment",begin:e,end:t, 61 | contains:[]},n);s.contains.push({scope:"doctag", 62 | begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", 63 | end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) 64 | ;const o=f("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,}/) 65 | ;return s.contains.push({begin:h(/[ ]+/,"(",o,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s 66 | },S=N("//","$"),M=N("/\\*","\\*/"),R=N("#","$");var j=Object.freeze({ 67 | __proto__:null,APOS_STRING_MODE:v,BACKSLASH_ESCAPE:O,BINARY_NUMBER_MODE:{ 68 | scope:"number",begin:_,relevance:0},BINARY_NUMBER_RE:_,COMMENT:N, 69 | C_BLOCK_COMMENT_MODE:M,C_LINE_COMMENT_MODE:S,C_NUMBER_MODE:{scope:"number", 70 | begin:y,relevance:0},C_NUMBER_RE:y,END_SAME_AS_BEGIN:e=>Object.assign(e,{ 71 | "on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ 72 | t.data._beginMatch!==e[1]&&t.ignoreMatch()}}),HASH_COMMENT_MODE:R,IDENT_RE:E, 73 | MATCH_NOTHING_RE:/\b\B/,METHOD_GUARD:{begin:"\\.\\s*"+x,relevance:0}, 74 | NUMBER_MODE:{scope:"number",begin:w,relevance:0},NUMBER_RE:w, 75 | PHRASAL_WORDS_MODE:{ 76 | 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/ 77 | },QUOTE_STRING_MODE:k,REGEXP_MODE:{scope:"regexp",begin:/\/(?=[^/\n]*\/)/, 78 | end:/\/[gimuy]*/,contains:[O,{begin:/\[/,end:/\]/,relevance:0,contains:[O]}]}, 79 | RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", 80 | SHEBANG:(e={})=>{const t=/^#![ ]*\// 81 | ;return e.binary&&(e.begin=h(t,/.*\b/,e.binary,/\b.*/)),i({scope:"meta",begin:t, 82 | end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, 83 | TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_IDENT_RE:x, 84 | UNDERSCORE_TITLE_MODE:{scope:"title",begin:x,relevance:0}});function A(e,t){ 85 | "."===e.input[e.index-1]&&t.ignoreMatch()}function I(e,t){ 86 | void 0!==e.className&&(e.scope=e.className,delete e.className)}function T(e,t){ 87 | t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", 88 | e.__beforeBegin=A,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, 89 | void 0===e.relevance&&(e.relevance=0))}function L(e,t){ 90 | Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function B(e,t){ 91 | if(e.match){ 92 | if(e.begin||e.end)throw Error("begin & end are not supported with match") 93 | ;e.begin=e.match,delete e.match}}function P(e,t){ 94 | void 0===e.relevance&&(e.relevance=1)}const D=(e,t)=>{if(!e.beforeMatch)return 95 | ;if(e.starts)throw Error("beforeMatch cannot be used with starts") 96 | ;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] 97 | })),e.keywords=n.keywords,e.begin=h(n.beforeMatch,g(n.begin)),e.starts={ 98 | relevance:0,contains:[Object.assign(n,{endsParent:!0})] 99 | },e.relevance=0,delete n.beforeMatch 100 | },H=["of","and","for","in","not","or","if","then","parent","list","value"],C="keyword" 101 | ;function $(e,t,n=C){const i=Object.create(null) 102 | ;return"string"==typeof e?s(n,e.split(" ")):Array.isArray(e)?s(n,e):Object.keys(e).forEach((n=>{ 103 | Object.assign(i,$(e[n],t,n))})),i;function s(e,n){ 104 | t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") 105 | ;i[n[0]]=[e,U(n[0],n[1])]}))}}function U(e,t){ 106 | return t?Number(t):(e=>H.includes(e.toLowerCase()))(e)?0:1}const z={},W=e=>{ 107 | console.error(e)},X=(e,...t)=>{console.log("WARN: "+e,...t)},G=(e,t)=>{ 108 | z[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),z[`${e}/${t}`]=!0) 109 | },K=Error();function F(e,t,{key:n}){let i=0;const s=e[n],o={},r={} 110 | ;for(let e=1;e<=t.length;e++)r[e+i]=s[e],o[e+i]=!0,i+=p(t[e-1]) 111 | ;e[n]=r,e[n]._emit=o,e[n]._multi=!0}function Z(e){(e=>{ 112 | e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, 113 | delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ 114 | _wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope 115 | }),(e=>{if(Array.isArray(e.begin)){ 116 | if(e.skip||e.excludeBegin||e.returnBegin)throw W("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), 117 | K 118 | ;if("object"!=typeof e.beginScope||null===e.beginScope)throw W("beginScope must be object"), 119 | K;F(e,e.begin,{key:"beginScope"}),e.begin=m(e.begin,{joinWith:""})}})(e),(e=>{ 120 | if(Array.isArray(e.end)){ 121 | if(e.skip||e.excludeEnd||e.returnEnd)throw W("skip, excludeEnd, returnEnd not compatible with endScope: {}"), 122 | K 123 | ;if("object"!=typeof e.endScope||null===e.endScope)throw W("endScope must be object"), 124 | K;F(e,e.end,{key:"endScope"}),e.end=m(e.end,{joinWith:""})}})(e)}function V(e){ 125 | function t(t,n){ 126 | return RegExp(l(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":"")) 127 | }class n{constructor(){ 128 | this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} 129 | addRule(e,t){ 130 | t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), 131 | this.matchAt+=p(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) 132 | ;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(m(e,{joinWith:"|" 133 | }),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex 134 | ;const t=this.matcherRe.exec(e);if(!t)return null 135 | ;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] 136 | ;return t.splice(0,n),Object.assign(t,i)}}class s{constructor(){ 137 | this.rules=[],this.multiRegexes=[], 138 | this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ 139 | if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n 140 | ;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), 141 | t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ 142 | return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ 143 | this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ 144 | const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex 145 | ;let n=t.exec(e) 146 | ;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ 147 | const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} 148 | return n&&(this.regexIndex+=n.position+1, 149 | this.regexIndex===this.count&&this.considerAll()),n}} 150 | if(e.compilerExtensions||(e.compilerExtensions=[]), 151 | e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") 152 | ;return e.classNameAliases=i(e.classNameAliases||{}),function n(o,r){const a=o 153 | ;if(o.isCompiled)return a 154 | ;[I,B,Z,D].forEach((e=>e(o,r))),e.compilerExtensions.forEach((e=>e(o,r))), 155 | o.__beforeBegin=null,[T,L,P].forEach((e=>e(o,r))),o.isCompiled=!0;let c=null 156 | ;return"object"==typeof o.keywords&&o.keywords.$pattern&&(o.keywords=Object.assign({},o.keywords), 157 | c=o.keywords.$pattern, 158 | delete o.keywords.$pattern),c=c||/\w+/,o.keywords&&(o.keywords=$(o.keywords,e.case_insensitive)), 159 | a.keywordPatternRe=t(c,!0), 160 | r&&(o.begin||(o.begin=/\B|\b/),a.beginRe=t(a.begin),o.end||o.endsWithParent||(o.end=/\B|\b/), 161 | o.end&&(a.endRe=t(a.end)), 162 | a.terminatorEnd=l(a.end)||"",o.endsWithParent&&r.terminatorEnd&&(a.terminatorEnd+=(o.end?"|":"")+r.terminatorEnd)), 163 | o.illegal&&(a.illegalRe=t(o.illegal)), 164 | o.contains||(o.contains=[]),o.contains=[].concat(...o.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>i(e,{ 165 | variants:null},t)))),e.cachedVariants?e.cachedVariants:q(e)?i(e,{ 166 | starts:e.starts?i(e.starts):null 167 | }):Object.isFrozen(e)?i(e):e))("self"===e?o:e)))),o.contains.forEach((e=>{n(e,a) 168 | })),o.starts&&n(o.starts,r),a.matcher=(e=>{const t=new s 169 | ;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" 170 | }))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" 171 | }),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function q(e){ 172 | return!!e&&(e.endsWithParent||q(e.starts))}class J extends Error{ 173 | constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}} 174 | const Y=n,Q=i,ee=Symbol("nomatch"),te=n=>{ 175 | const i=Object.create(null),s=Object.create(null),o=[];let r=!0 176 | ;const a="Could not find the language '{}', did you forget to load/include a language module?",l={ 177 | disableAutodetect:!0,name:"Plain text",contains:[]};let p={ 178 | ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, 179 | languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", 180 | cssSelector:"pre code",languages:null,__emitter:c};function b(e){ 181 | return p.noHighlightRe.test(e)}function m(e,t,n){let i="",s="" 182 | ;"object"==typeof t?(i=e, 183 | n=t.ignoreIllegals,s=t.language):(G("10.7.0","highlight(lang, code, ...args) has been deprecated."), 184 | G("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), 185 | s=e,i=t),void 0===n&&(n=!0);const o={code:i,language:s};N("before:highlight",o) 186 | ;const r=o.result?o.result:E(o.language,o.code,n) 187 | ;return r.code=o.code,N("after:highlight",r),r}function E(e,n,s,o){ 188 | const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(R) 189 | ;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(R),n="" 190 | ;for(;t;){n+=R.substring(e,t.index) 191 | ;const s=_.case_insensitive?t[0].toLowerCase():t[0],o=(i=s,N.keywords[i]);if(o){ 192 | const[e,i]=o 193 | ;if(M.addText(n),n="",c[s]=(c[s]||0)+1,c[s]<=7&&(j+=i),e.startsWith("_"))n+=t[0];else{ 194 | const n=_.classNameAliases[e]||e;u(t[0],n)}}else n+=t[0] 195 | ;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(R)}var i 196 | ;n+=R.substring(e),M.addText(n)}function g(){null!=N.subLanguage?(()=>{ 197 | if(""===R)return;let e=null;if("string"==typeof N.subLanguage){ 198 | if(!i[N.subLanguage])return void M.addText(R) 199 | ;e=E(N.subLanguage,R,!0,S[N.subLanguage]),S[N.subLanguage]=e._top 200 | }else e=x(R,N.subLanguage.length?N.subLanguage:null) 201 | ;N.relevance>0&&(j+=e.relevance),M.__addSublanguage(e._emitter,e.language) 202 | })():l(),R=""}function u(e,t){ 203 | ""!==e&&(M.startScope(t),M.addText(e),M.endScope())}function d(e,t){let n=1 204 | ;const i=t.length-1;for(;n<=i;){if(!e._emit[n]){n++;continue} 205 | const i=_.classNameAliases[e[n]]||e[n],s=t[n];i?u(s,i):(R=s,l(),R=""),n++}} 206 | function h(e,t){ 207 | return e.scope&&"string"==typeof e.scope&&M.openNode(_.classNameAliases[e.scope]||e.scope), 208 | e.beginScope&&(e.beginScope._wrap?(u(R,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), 209 | R=""):e.beginScope._multi&&(d(e.beginScope,t),R="")),N=Object.create(e,{parent:{ 210 | value:N}}),N}function f(e,n,i){let s=((e,t)=>{const n=e&&e.exec(t) 211 | ;return n&&0===n.index})(e.endRe,i);if(s){if(e["on:end"]){const i=new t(e) 212 | ;e["on:end"](n,i),i.isMatchIgnored&&(s=!1)}if(s){ 213 | for(;e.endsParent&&e.parent;)e=e.parent;return e}} 214 | if(e.endsWithParent)return f(e.parent,n,i)}function b(e){ 215 | return 0===N.matcher.regexIndex?(R+=e[0],1):(T=!0,0)}function m(e){ 216 | const t=e[0],i=n.substring(e.index),s=f(N,e,i);if(!s)return ee;const o=N 217 | ;N.endScope&&N.endScope._wrap?(g(), 218 | u(t,N.endScope._wrap)):N.endScope&&N.endScope._multi?(g(), 219 | d(N.endScope,e)):o.skip?R+=t:(o.returnEnd||o.excludeEnd||(R+=t), 220 | g(),o.excludeEnd&&(R=t));do{ 221 | N.scope&&M.closeNode(),N.skip||N.subLanguage||(j+=N.relevance),N=N.parent 222 | }while(N!==s.parent);return s.starts&&h(s.starts,e),o.returnEnd?0:t.length} 223 | let w={};function y(i,o){const a=o&&o[0];if(R+=i,null==a)return g(),0 224 | ;if("begin"===w.type&&"end"===o.type&&w.index===o.index&&""===a){ 225 | if(R+=n.slice(o.index,o.index+1),!r){const t=Error(`0 width match regex (${e})`) 226 | ;throw t.languageName=e,t.badRule=w.rule,t}return 1} 227 | if(w=o,"begin"===o.type)return(e=>{ 228 | const n=e[0],i=e.rule,s=new t(i),o=[i.__beforeBegin,i["on:begin"]] 229 | ;for(const t of o)if(t&&(t(e,s),s.isMatchIgnored))return b(n) 230 | ;return i.skip?R+=n:(i.excludeBegin&&(R+=n), 231 | g(),i.returnBegin||i.excludeBegin||(R=n)),h(i,e),i.returnBegin?0:n.length})(o) 232 | ;if("illegal"===o.type&&!s){ 233 | const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"")+'"') 234 | ;throw e.mode=N,e}if("end"===o.type){const e=m(o);if(e!==ee)return e} 235 | if("illegal"===o.type&&""===a)return 1 236 | ;if(I>1e5&&I>3*o.index)throw Error("potential infinite loop, way more iterations than matches") 237 | ;return R+=a,a.length}const _=O(e) 238 | ;if(!_)throw W(a.replace("{}",e)),Error('Unknown language: "'+e+'"') 239 | ;const v=V(_);let k="",N=o||v;const S={},M=new p.__emitter(p);(()=>{const e=[] 240 | ;for(let t=N;t!==_;t=t.parent)t.scope&&e.unshift(t.scope) 241 | ;e.forEach((e=>M.openNode(e)))})();let R="",j=0,A=0,I=0,T=!1;try{ 242 | if(_.__emitTokens)_.__emitTokens(n,M);else{for(N.matcher.considerAll();;){ 243 | I++,T?T=!1:N.matcher.considerAll(),N.matcher.lastIndex=A 244 | ;const e=N.matcher.exec(n);if(!e)break;const t=y(n.substring(A,e.index),e) 245 | ;A=e.index+t}y(n.substring(A))}return M.finalize(),k=M.toHTML(),{language:e, 246 | value:k,relevance:j,illegal:!1,_emitter:M,_top:N}}catch(t){ 247 | if(t.message&&t.message.includes("Illegal"))return{language:e,value:Y(n), 248 | illegal:!0,relevance:0,_illegalBy:{message:t.message,index:A, 249 | context:n.slice(A-100,A+100),mode:t.mode,resultSoFar:k},_emitter:M};if(r)return{ 250 | language:e,value:Y(n),illegal:!1,relevance:0,errorRaised:t,_emitter:M,_top:N} 251 | ;throw t}}function x(e,t){t=t||p.languages||Object.keys(i);const n=(e=>{ 252 | const t={value:Y(e),illegal:!1,relevance:0,_top:l,_emitter:new p.__emitter(p)} 253 | ;return t._emitter.addText(e),t})(e),s=t.filter(O).filter(k).map((t=>E(t,e,!1))) 254 | ;s.unshift(n);const o=s.sort(((e,t)=>{ 255 | if(e.relevance!==t.relevance)return t.relevance-e.relevance 256 | ;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1 257 | ;if(O(t.language).supersetOf===e.language)return-1}return 0})),[r,a]=o,c=r 258 | ;return c.secondBest=a,c}function w(e){let t=null;const n=(e=>{ 259 | let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" 260 | ;const n=p.languageDetectRe.exec(t);if(n){const t=O(n[1]) 261 | ;return t||(X(a.replace("{}",n[1])), 262 | X("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} 263 | return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return 264 | ;if(N("before:highlightElement",{el:e,language:n 265 | }),e.dataset.highlighted)return void console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",e) 266 | ;if(e.children.length>0&&(p.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), 267 | console.warn("https://github.com/highlightjs/highlight.js/wiki/security"), 268 | console.warn("The element with unescaped HTML:"), 269 | console.warn(e)),p.throwUnescapedHTML))throw new J("One of your code blocks includes unescaped HTML.",e.innerHTML) 270 | ;t=e;const i=t.textContent,o=n?m(i,{language:n,ignoreIllegals:!0}):x(i) 271 | ;e.innerHTML=o.value,e.dataset.highlighted="yes",((e,t,n)=>{const i=t&&s[t]||n 272 | ;e.classList.add("hljs"),e.classList.add("language-"+i) 273 | })(e,n,o.language),e.result={language:o.language,re:o.relevance, 274 | relevance:o.relevance},o.secondBest&&(e.secondBest={ 275 | language:o.secondBest.language,relevance:o.secondBest.relevance 276 | }),N("after:highlightElement",{el:e,result:o,text:i})}let y=!1;function _(){ 277 | "loading"!==document.readyState?document.querySelectorAll(p.cssSelector).forEach(w):y=!0 278 | }function O(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]} 279 | function v(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ 280 | s[e.toLowerCase()]=t}))}function k(e){const t=O(e) 281 | ;return t&&!t.disableAutodetect}function N(e,t){const n=e;o.forEach((e=>{ 282 | e[n]&&e[n](t)}))} 283 | "undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ 284 | y&&_()}),!1),Object.assign(n,{highlight:m,highlightAuto:x,highlightAll:_, 285 | highlightElement:w, 286 | highlightBlock:e=>(G("10.7.0","highlightBlock will be removed entirely in v12.0"), 287 | G("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{p=Q(p,e)}, 288 | initHighlighting:()=>{ 289 | _(),G("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, 290 | initHighlightingOnLoad:()=>{ 291 | _(),G("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") 292 | },registerLanguage:(e,t)=>{let s=null;try{s=t(n)}catch(t){ 293 | if(W("Language definition for '{}' could not be registered.".replace("{}",e)), 294 | !r)throw t;W(t),s=l} 295 | s.name||(s.name=e),i[e]=s,s.rawDefinition=t.bind(null,n),s.aliases&&v(s.aliases,{ 296 | languageName:e})},unregisterLanguage:e=>{delete i[e] 297 | ;for(const t of Object.keys(s))s[t]===e&&delete s[t]}, 298 | listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:v, 299 | autoDetection:k,inherit:Q,addPlugin:e=>{(e=>{ 300 | e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ 301 | e["before:highlightBlock"](Object.assign({block:t.el},t)) 302 | }),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ 303 | e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),o.push(e)}, 304 | removePlugin:e=>{const t=o.indexOf(e);-1!==t&&o.splice(t,1)}}),n.debugMode=()=>{ 305 | r=!1},n.safeMode=()=>{r=!0},n.versionString="11.9.0",n.regex={concat:h, 306 | lookahead:g,either:f,optional:d,anyNumberOfTimes:u} 307 | ;for(const t in j)"object"==typeof j[t]&&e(j[t]);return Object.assign(n,j),n 308 | },ne=te({});return ne.newInstance=()=>te({}),ne}() 309 | ;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `bash` grammar compiled for Highlight.js 11.9.0 */ 310 | (()=>{var e=(()=>{"use strict";return e=>{const s=e.regex,t={},n={begin:/\$\{/, 311 | end:/\}/,contains:["self",{begin:/:-/,contains:[t]}]};Object.assign(t,{ 312 | className:"variable",variants:[{ 313 | begin:s.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},n]});const a={ 314 | className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE] 315 | },i=e.inherit(e.COMMENT(),{match:[/(^|\s)/,/#.*$/],scope:{2:"comment"}}),c={ 316 | begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/, 317 | end:/(\w+)/,className:"string"})]}},o={className:"string",begin:/"/,end:/"/, 318 | contains:[e.BACKSLASH_ESCAPE,t,a]};a.contains.push(o);const r={begin:/\$?\(\(/, 319 | end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,t] 320 | },l=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 321 | }),m={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, 322 | contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ 323 | name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z][a-z0-9._-]+\b/, 324 | keyword:["if","then","else","elif","fi","for","while","until","in","do","done","case","esac","function","select"], 325 | literal:["true","false"], 326 | 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","chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","b2sum","base32","base64","cat","cksum","comm","csplit","cut","expand","fmt","fold","head","join","md5sum","nl","numfmt","od","paste","ptx","pr","sha1sum","sha224sum","sha256sum","sha384sum","sha512sum","shuf","sort","split","sum","tac","tail","tr","tsort","unexpand","uniq","wc","arch","basename","chroot","date","dirname","du","echo","env","expr","factor","groups","hostid","id","link","logname","nice","nohup","nproc","pathchk","pinky","printenv","printf","pwd","readlink","runcon","seq","sleep","stat","stdbuf","stty","tee","test","timeout","tty","uname","unlink","uptime","users","who","whoami","yes"] 327 | },contains:[l,e.SHEBANG(),m,r,i,c,{match:/(\/[a-z._-]+)+/},o,{match:/\\"/},{ 328 | className:"string",begin:/'/,end:/'/},{match:/\\'/},t]}}})() 329 | ;hljs.registerLanguage("bash",e)})();/*! `c` grammar compiled for Highlight.js 11.9.0 */ 330 | (()=>{var e=(()=>{"use strict";return e=>{const n=e.regex,t=e.COMMENT("//","$",{ 331 | contains:[{begin:/\\\n/}] 332 | }),s="decltype\\(auto\\)",a="[a-zA-Z_]\\w*::",r="("+s+"|"+n.optional(a)+"[a-zA-Z_]\\w*"+n.optional("<[^<>]+>")+")",i={ 333 | className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{ 334 | match:/\batomic_[a-z]{3,6}\b/}]},l={className:"string",variants:[{ 335 | begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{ 336 | begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", 337 | end:"'",illegal:"."},e.END_SAME_AS_BEGIN({ 338 | begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={ 339 | className:"number",variants:[{begin:"\\b(0b[01']+)"},{ 340 | begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" 341 | },{ 342 | begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" 343 | }],relevance:0},c={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ 344 | keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" 345 | },contains:[{begin:/\\\n/,relevance:0},e.inherit(l,{className:"string"}),{ 346 | className:"string",begin:/<.*?>/},t,e.C_BLOCK_COMMENT_MODE]},d={ 347 | className:"title",begin:n.optional(a)+e.IDENT_RE,relevance:0 348 | },g=n.optional(a)+e.IDENT_RE+"\\s*\\(",u={ 349 | keyword:["asm","auto","break","case","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","struct","switch","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"], 350 | type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal128","const","static","complex","bool","imaginary"], 351 | literal:"true false NULL", 352 | built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr" 353 | },m=[c,i,t,e.C_BLOCK_COMMENT_MODE,o,l],_={variants:[{begin:/=/,end:/;/},{ 354 | begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}], 355 | keywords:u,contains:m.concat([{begin:/\(/,end:/\)/,keywords:u, 356 | contains:m.concat(["self"]),relevance:0}]),relevance:0},p={ 357 | begin:"("+r+"[\\*&\\s]+)+"+g,returnBegin:!0,end:/[{;=]/,excludeEnd:!0, 358 | keywords:u,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:s,keywords:u,relevance:0},{ 359 | begin:g,returnBegin:!0,contains:[e.inherit(d,{className:"title.function"})], 360 | relevance:0},{relevance:0,match:/,/},{className:"params",begin:/\(/,end:/\)/, 361 | keywords:u,relevance:0,contains:[t,e.C_BLOCK_COMMENT_MODE,l,o,i,{begin:/\(/, 362 | end:/\)/,keywords:u,relevance:0,contains:["self",t,e.C_BLOCK_COMMENT_MODE,l,o,i] 363 | }]},i,t,e.C_BLOCK_COMMENT_MODE,c]};return{name:"C",aliases:["h"],keywords:u, 364 | disableAutodetect:!0,illegal:"=]/,contains:[{ 367 | beginKeywords:"final class struct"},e.TITLE_MODE]}]),exports:{preprocessor:c, 368 | strings:l,keywords:u}}}})();hljs.registerLanguage("c",e)})();/*! `cpp` grammar compiled for Highlight.js 11.9.0 */ 369 | (()=>{var e=(()=>{"use strict";return e=>{const t=e.regex,a=e.COMMENT("//","$",{ 370 | contains:[{begin:/\\\n/}] 371 | }),n="decltype\\(auto\\)",r="[a-zA-Z_]\\w*::",i="(?!struct)("+n+"|"+t.optional(r)+"[a-zA-Z_]\\w*"+t.optional("<[^<>]+>")+")",s={ 372 | className:"type",begin:"\\b[a-z\\d_]*_t\\b"},c={className:"string",variants:[{ 373 | begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{ 374 | begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", 375 | end:"'",illegal:"."},e.END_SAME_AS_BEGIN({ 376 | begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={ 377 | className:"number",variants:[{ 378 | begin:"[+-]?(?:(?:[0-9](?:'?[0-9])*\\.(?:[0-9](?:'?[0-9])*)?|\\.[0-9](?:'?[0-9])*)(?:[Ee][+-]?[0-9](?:'?[0-9])*)?|[0-9](?:'?[0-9])*[Ee][+-]?[0-9](?:'?[0-9])*|0[Xx](?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*(?:\\.(?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)?)?|\\.[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)[Pp][+-]?[0-9](?:'?[0-9])*)(?:[Ff](?:16|32|64|128)?|(BF|bf)16|[Ll]|)" 379 | },{ 380 | begin:"[+-]?\\b(?:0[Bb][01](?:'?[01])*|0[Xx][0-9A-Fa-f](?:'?[0-9A-Fa-f])*|0(?:'?[0-7])*|[1-9](?:'?[0-9])*)(?:[Uu](?:LL?|ll?)|[Uu][Zz]?|(?:LL?|ll?)[Uu]?|[Zz][Uu]|)" 381 | }],relevance:0},l={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ 382 | keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" 383 | },contains:[{begin:/\\\n/,relevance:0},e.inherit(c,{className:"string"}),{ 384 | className:"string",begin:/<.*?>/},a,e.C_BLOCK_COMMENT_MODE]},u={ 385 | className:"title",begin:t.optional(r)+e.IDENT_RE,relevance:0 386 | },d=t.optional(r)+e.IDENT_RE+"\\s*\\(",p={ 387 | type:["bool","char","char16_t","char32_t","char8_t","double","float","int","long","short","void","wchar_t","unsigned","signed","const","static"], 388 | keyword:["alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit","atomic_noexcept","auto","bitand","bitor","break","case","catch","class","co_await","co_return","co_yield","compl","concept","const_cast|10","consteval","constexpr","constinit","continue","decltype","default","delete","do","dynamic_cast|10","else","enum","explicit","export","extern","false","final","for","friend","goto","if","import","inline","module","mutable","namespace","new","noexcept","not","not_eq","nullptr","operator","or","or_eq","override","private","protected","public","reflexpr","register","reinterpret_cast|10","requires","return","sizeof","static_assert","static_cast|10","struct","switch","synchronized","template","this","thread_local","throw","transaction_safe","transaction_safe_dynamic","true","try","typedef","typeid","typename","union","using","virtual","volatile","while","xor","xor_eq"], 389 | literal:["NULL","false","nullopt","nullptr","true"],built_in:["_Pragma"], 390 | _type_hints:["any","auto_ptr","barrier","binary_semaphore","bitset","complex","condition_variable","condition_variable_any","counting_semaphore","deque","false_type","future","imaginary","initializer_list","istringstream","jthread","latch","lock_guard","multimap","multiset","mutex","optional","ostringstream","packaged_task","pair","promise","priority_queue","queue","recursive_mutex","recursive_timed_mutex","scoped_lock","set","shared_future","shared_lock","shared_mutex","shared_timed_mutex","shared_ptr","stack","string_view","stringstream","timed_mutex","thread","true_type","tuple","unique_lock","unique_ptr","unordered_map","unordered_multimap","unordered_multiset","unordered_set","variant","vector","weak_ptr","wstring","wstring_view"] 391 | },_={className:"function.dispatch",relevance:0,keywords:{ 392 | _hint:["abort","abs","acos","apply","as_const","asin","atan","atan2","calloc","ceil","cerr","cin","clog","cos","cosh","cout","declval","endl","exchange","exit","exp","fabs","floor","fmod","forward","fprintf","fputs","free","frexp","fscanf","future","invoke","isalnum","isalpha","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit","labs","launder","ldexp","log","log10","make_pair","make_shared","make_shared_for_overwrite","make_tuple","make_unique","malloc","memchr","memcmp","memcpy","memset","modf","move","pow","printf","putchar","puts","realloc","scanf","sin","sinh","snprintf","sprintf","sqrt","sscanf","std","stderr","stdin","stdout","strcat","strchr","strcmp","strcpy","strcspn","strlen","strncat","strncmp","strncpy","strpbrk","strrchr","strspn","strstr","swap","tan","tanh","terminate","to_underlying","tolower","toupper","vfprintf","visit","vprintf","vsprintf"] 393 | }, 394 | begin:t.concat(/\b/,/(?!decltype)/,/(?!if)/,/(?!for)/,/(?!switch)/,/(?!while)/,e.IDENT_RE,t.lookahead(/(<[^<>]+>|)\s*\(/)) 395 | },m=[_,l,s,a,e.C_BLOCK_COMMENT_MODE,o,c],f={variants:[{begin:/=/,end:/;/},{ 396 | begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}], 397 | keywords:p,contains:m.concat([{begin:/\(/,end:/\)/,keywords:p, 398 | contains:m.concat(["self"]),relevance:0}]),relevance:0},g={className:"function", 399 | begin:"("+i+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0, 400 | keywords:p,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:n,keywords:p,relevance:0},{ 401 | begin:d,returnBegin:!0,contains:[u],relevance:0},{begin:/::/,relevance:0},{ 402 | begin:/:/,endsWithParent:!0,contains:[c,o]},{relevance:0,match:/,/},{ 403 | className:"params",begin:/\(/,end:/\)/,keywords:p,relevance:0, 404 | contains:[a,e.C_BLOCK_COMMENT_MODE,c,o,s,{begin:/\(/,end:/\)/,keywords:p, 405 | relevance:0,contains:["self",a,e.C_BLOCK_COMMENT_MODE,c,o,s]}] 406 | },s,a,e.C_BLOCK_COMMENT_MODE,l]};return{name:"C++", 407 | aliases:["cc","c++","h++","hpp","hh","hxx","cxx"],keywords:p,illegal:"",keywords:p,contains:["self",s]},{begin:e.IDENT_RE+"::",keywords:p},{ 412 | match:[/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,/\s+/,/\w+/], 413 | className:{1:"keyword",3:"title.class"}}])}}})();hljs.registerLanguage("cpp",e) 414 | })();/*! `css` grammar compiled for Highlight.js 11.9.0 */ 415 | (()=>{var e=(()=>{"use strict" 416 | ;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","defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],r=["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"].sort().reverse(),o=["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"].sort().reverse(),t=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),i=["align-content","align-items","align-self","alignment-baseline","all","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","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-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-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","cx","cy","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","content","content-visibility","counter-increment","counter-reset","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","empty-cells","enable-background","fill","fill-opacity","fill-rule","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flow","flood-color","flood-opacity","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-synthesis","font-variant","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","gap","glyph-orientation-horizontal","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inline-size","isolation","kerning","justify-content","left","letter-spacing","lighting-color","line-break","line-height","list-style","list-style-image","list-style-position","list-style-type","marker","marker-end","marker-mid","marker-start","mask","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","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-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","pause","pause-after","pause-before","perspective","perspective-origin","pointer-events","position","quotes","r","resize","rest","rest-after","rest-before","right","row-gap","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","shape-rendering","stop-color","stop-opacity","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","speak","speak-as","src","tab-size","table-layout","text-anchor","text-align","text-align-all","text-align-last","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-box","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vector-effect","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","x","y","z-index"].sort().reverse() 417 | ;return n=>{const a=n.regex,l=(e=>({IMPORTANT:{scope:"meta",begin:"!important"}, 418 | BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number", 419 | begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{ 420 | className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{ 421 | scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", 422 | contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{ 423 | scope:"number", 424 | 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)?", 425 | relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/} 426 | }))(n),s=[n.APOS_STRING_MODE,n.QUOTE_STRING_MODE];return{name:"CSS", 427 | case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"}, 428 | classNameAliases:{keyframePosition:"selector-tag"},contains:[l.BLOCK_COMMENT,{ 429 | begin:/-(webkit|moz|ms|o)-(?=[a-z])/},l.CSS_NUMBER_MODE,{ 430 | className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0},{ 431 | className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0 432 | },l.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{ 433 | begin:":("+o.join("|")+")"},{begin:":(:)?("+t.join("|")+")"}]},l.CSS_VARIABLE,{ 434 | className:"attribute",begin:"\\b("+i.join("|")+")\\b"},{begin:/:/,end:/[;}{]/, 435 | contains:[l.BLOCK_COMMENT,l.HEXCOLOR,l.IMPORTANT,l.CSS_NUMBER_MODE,...s,{ 436 | begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri" 437 | },contains:[...s,{className:"string",begin:/[^)]/,endsWithParent:!0, 438 | excludeEnd:!0}]},l.FUNCTION_DISPATCH]},{begin:a.lookahead(/@/),end:"[{;]", 439 | relevance:0,illegal:/:/,contains:[{className:"keyword",begin:/@-?\w[\w]*(-\w+)*/ 440 | },{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{ 441 | $pattern:/[a-z-]+/,keyword:"and or not only",attribute:r.join(" ")},contains:[{ 442 | begin:/[a-z-]+(?=:)/,className:"attribute"},...s,l.CSS_NUMBER_MODE]}]},{ 443 | className:"selector-tag",begin:"\\b("+e.join("|")+")\\b"}]}}})() 444 | ;hljs.registerLanguage("css",e)})();/*! `diff` grammar compiled for Highlight.js 11.9.0 */ 445 | (()=>{var e=(()=>{"use strict";return e=>{const a=e.regex;return{name:"Diff", 446 | aliases:["patch"],contains:[{className:"meta",relevance:10, 447 | match:a.either(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/) 448 | },{className:"comment",variants:[{ 449 | begin:a.either(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/), 450 | end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{ 451 | className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/, 452 | end:/$/}]}}})();hljs.registerLanguage("diff",e)})();/*! `dockerfile` grammar compiled for Highlight.js 11.9.0 */ 453 | (()=>{var e=(()=>{"use strict";return e=>({name:"Dockerfile",aliases:["docker"], 454 | case_insensitive:!0, 455 | keywords:["from","maintainer","expose","env","arg","user","onbuild","stopsignal"], 456 | contains:[e.HASH_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE,{ 457 | beginKeywords:"run cmd entrypoint volume add copy workdir label healthcheck shell", 458 | starts:{end:/[^\\]$/,subLanguage:"bash"}}],illegal:"{var e=(()=>{"use strict";return e=>{const n={ 461 | keyword:["break","case","chan","const","continue","default","defer","else","fallthrough","for","func","go","goto","if","import","interface","map","package","range","return","select","struct","switch","type","var"], 462 | type:["bool","byte","complex64","complex128","error","float32","float64","int8","int16","int32","int64","string","uint8","uint16","uint32","uint64","int","uint","uintptr","rune"], 463 | literal:["true","false","iota","nil"], 464 | built_in:["append","cap","close","complex","copy","imag","len","make","new","panic","print","println","real","recover","delete"] 465 | };return{name:"Go",aliases:["golang"],keywords:n,illegal:"{var e=(()=>{"use strict" 474 | ;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","sessionStorage","module","global"],i=[].concat(r,t,s) 475 | ;return o=>{const l=o.regex,b=e,d={begin:/<[A-Za-z0-9\\._:-]+/, 476 | end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ 477 | const a=e[0].length+e.index,t=e.input[a] 478 | ;if("<"===t||","===t)return void n.ignoreMatch();let s 479 | ;">"===t&&(((e,{after:n})=>{const a="",$={ 525 | match:[/const|var|let/,/\s+/,b,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(B)], 526 | keywords:"async",className:{1:"keyword",3:"title.function"},contains:[R]} 527 | ;return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{ 528 | PARAMS_CONTAINS:w,CLASS_REFERENCE:k},illegal:/#(?![$_A-z])/, 529 | contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{ 530 | label:"use_strict",className:"meta",relevance:10, 531 | begin:/^\s*['"]use (strict|asm)['"]/ 532 | },o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,h,N,_,f,v,{match:/\$\d+/},A,k,{ 533 | className:"attr",begin:b+l.lookahead(":"),relevance:0},$,{ 534 | begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", 535 | keywords:"return throw case",relevance:0,contains:[v,o.REGEXP_MODE,{ 536 | className:"function",begin:B,returnBegin:!0,end:"\\s*=>",contains:[{ 537 | className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{ 538 | className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0, 539 | excludeEnd:!0,keywords:g,contains:w}]}]},{begin:/,/,relevance:0},{match:/\s+/, 540 | relevance:0},{variants:[{begin:"<>",end:""},{ 541 | match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:d.begin, 542 | "on:begin":d.isTrulyOpeningTag,end:d.end}],subLanguage:"xml",contains:[{ 543 | begin:d.begin,end:d.end,skip:!0,contains:["self"]}]}]},I,{ 544 | beginKeywords:"while if switch catch for"},{ 545 | begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", 546 | returnBegin:!0,label:"func.def",contains:[R,o.inherit(o.TITLE_MODE,{begin:b, 547 | className:"title.function"})]},{match:/\.\.\./,relevance:0},C,{match:"\\$"+b, 548 | relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, 549 | contains:[R]},x,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/, 550 | className:"variable.constant"},O,M,{match:/\$[(.]/}]}}})() 551 | ;hljs.registerLanguage("javascript",e)})();/*! `json` grammar compiled for Highlight.js 11.9.0 */ 552 | (()=>{var e=(()=>{"use strict";return e=>{const a=["true","false","null"],n={ 553 | scope:"literal",beginKeywords:a.join(" ")};return{name:"JSON",keywords:{ 554 | literal:a},contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/, 555 | relevance:1.01},{match:/[{}[\],:]/,className:"punctuation",relevance:0 556 | },e.QUOTE_STRING_MODE,n,e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE], 557 | illegal:"\\S"}}})();hljs.registerLanguage("json",e)})();/*! `lua` grammar compiled for Highlight.js 11.9.0 */ 558 | (()=>{var e=(()=>{"use strict";return e=>{const t="\\[=*\\[",a="\\]=*\\]",n={ 559 | begin:t,end:a,contains:["self"] 560 | },o=[e.COMMENT("--(?!"+t+")","$"),e.COMMENT("--"+t,a,{contains:[n],relevance:10 561 | })];return{name:"Lua",keywords:{$pattern:e.UNDERSCORE_IDENT_RE, 562 | literal:"true false nil", 563 | keyword:"and break do else elseif end for goto if in local not or repeat return then until while", 564 | built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove" 565 | },contains:o.concat([{className:"function",beginKeywords:"function",end:"\\)", 566 | contains:[e.inherit(e.TITLE_MODE,{ 567 | begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params", 568 | begin:"\\(",endsWithParent:!0,contains:o}].concat(o) 569 | },e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string", 570 | begin:t,end:a,contains:[n],relevance:5}])}}})();hljs.registerLanguage("lua",e) 571 | })();/*! `makefile` grammar compiled for Highlight.js 11.9.0 */ 572 | (()=>{var e=(()=>{"use strict";return e=>{const i={className:"variable", 573 | variants:[{begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)", 574 | contains:[e.BACKSLASH_ESCAPE]},{begin:/\$[@%{var e=(()=>{"use strict";return e=>{const n={begin:/<\/?[A-Za-z_]/, 586 | end:">",subLanguage:"xml",relevance:0},a={variants:[{begin:/\[.+?\]\[.*?\]/, 587 | relevance:0},{ 588 | begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, 589 | relevance:2},{ 590 | begin:e.regex.concat(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), 591 | relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ 592 | begin:/\[.*?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{match:/\[(?=\])/ 593 | },{className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, 594 | returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", 595 | excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", 596 | end:"\\]",excludeBegin:!0,excludeEnd:!0}]},i={className:"strong",contains:[], 597 | variants:[{begin:/_{2}(?!\s)/,end:/_{2}/},{begin:/\*{2}(?!\s)/,end:/\*{2}/}] 598 | },s={className:"emphasis",contains:[],variants:[{begin:/\*(?![*\s])/,end:/\*/},{ 599 | begin:/_(?![_\s])/,end:/_/,relevance:0}]},c=e.inherit(i,{contains:[] 600 | }),t=e.inherit(s,{contains:[]});i.contains.push(t),s.contains.push(c) 601 | ;let g=[n,a];return[i,s,c,t].forEach((e=>{e.contains=e.contains.concat(g) 602 | })),g=g.concat(i,s),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ 603 | className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:g},{ 604 | begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", 605 | contains:g}]}]},n,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", 606 | end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:g, 607 | end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ 608 | begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ 609 | begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", 610 | contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ 611 | begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ 612 | className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ 613 | className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})() 614 | ;hljs.registerLanguage("markdown",e)})();/*! `nginx` grammar compiled for Highlight.js 11.9.0 */ 615 | (()=>{var e=(()=>{"use strict";return e=>{const n=e.regex,a={ 616 | className:"variable",variants:[{begin:/\$\d+/},{begin:/\$\{\w+\}/},{ 617 | begin:n.concat(/[$@]/,e.UNDERSCORE_IDENT_RE)}]},s={endsWithParent:!0,keywords:{ 618 | $pattern:/[a-z_]{2,}|\/dev\/poll/, 619 | literal:["on","off","yes","no","true","false","none","blocked","debug","info","notice","warn","error","crit","select","break","last","permanent","redirect","kqueue","rtsig","epoll","poll","/dev/poll"] 620 | },relevance:0,illegal:"=>",contains:[e.HASH_COMMENT_MODE,{className:"string", 621 | contains:[e.BACKSLASH_ESCAPE,a],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/ 622 | }]},{begin:"([a-z]+):/",end:"\\s",endsWithParent:!0,excludeEnd:!0,contains:[a] 623 | },{className:"regexp",contains:[e.BACKSLASH_ESCAPE,a],variants:[{begin:"\\s\\^", 624 | end:"\\s|\\{|;",returnEnd:!0},{begin:"~\\*?\\s+",end:"\\s|\\{|;",returnEnd:!0},{ 625 | begin:"\\*(\\.[a-z\\-]+)+"},{begin:"([a-z\\-]+\\.)+\\*"}]},{className:"number", 626 | begin:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{ 627 | className:"number",begin:"\\b\\d+[kKmMgGdshdwy]?\\b",relevance:0},a]};return{ 628 | name:"Nginx config",aliases:["nginxconf"],contains:[e.HASH_COMMENT_MODE,{ 629 | beginKeywords:"upstream location",end:/;|\{/,contains:s.contains,keywords:{ 630 | section:"upstream location"}},{className:"section", 631 | begin:n.concat(e.UNDERSCORE_IDENT_RE+n.lookahead(/\s+\{/)),relevance:0},{ 632 | begin:n.lookahead(e.UNDERSCORE_IDENT_RE+"\\s"),end:";|\\{",contains:[{ 633 | className:"attribute",begin:e.UNDERSCORE_IDENT_RE,starts:s}],relevance:0}], 634 | illegal:"[^\\s\\}\\{]"}}})();hljs.registerLanguage("nginx",e)})();/*! `pgsql` grammar compiled for Highlight.js 11.9.0 */ 635 | (()=>{var E=(()=>{"use strict";return E=>{ 636 | const T=E.COMMENT("--","$"),N="\\$([a-zA-Z_]?|[a-zA-Z_][a-zA-Z_0-9]*)\\$",A="BIGINT INT8 BIGSERIAL SERIAL8 BIT VARYING VARBIT BOOLEAN BOOL BOX BYTEA CHARACTER CHAR VARCHAR CIDR CIRCLE DATE DOUBLE PRECISION FLOAT8 FLOAT INET INTEGER INT INT4 INTERVAL JSON JSONB LINE LSEG|10 MACADDR MACADDR8 MONEY NUMERIC DEC DECIMAL PATH POINT POLYGON REAL FLOAT4 SMALLINT INT2 SMALLSERIAL|10 SERIAL2|10 SERIAL|10 SERIAL4|10 TEXT TIME ZONE TIMETZ|10 TIMESTAMP TIMESTAMPTZ|10 TSQUERY|10 TSVECTOR|10 TXID_SNAPSHOT|10 UUID XML NATIONAL NCHAR INT4RANGE|10 INT8RANGE|10 NUMRANGE|10 TSRANGE|10 TSTZRANGE|10 DATERANGE|10 ANYELEMENT ANYARRAY ANYNONARRAY ANYENUM ANYRANGE CSTRING INTERNAL RECORD PG_DDL_COMMAND VOID UNKNOWN OPAQUE REFCURSOR NAME OID REGPROC|10 REGPROCEDURE|10 REGOPER|10 REGOPERATOR|10 REGCLASS|10 REGTYPE|10 REGROLE|10 REGNAMESPACE|10 REGCONFIG|10 REGDICTIONARY|10 ",R=A.trim().split(" ").map((E=>E.split("|")[0])).join("|"),I="ARRAY_AGG AVG BIT_AND BIT_OR BOOL_AND BOOL_OR COUNT EVERY JSON_AGG JSONB_AGG JSON_OBJECT_AGG JSONB_OBJECT_AGG MAX MIN MODE STRING_AGG SUM XMLAGG CORR COVAR_POP COVAR_SAMP REGR_AVGX REGR_AVGY REGR_COUNT REGR_INTERCEPT REGR_R2 REGR_SLOPE REGR_SXX REGR_SXY REGR_SYY STDDEV STDDEV_POP STDDEV_SAMP VARIANCE VAR_POP VAR_SAMP PERCENTILE_CONT PERCENTILE_DISC ROW_NUMBER RANK DENSE_RANK PERCENT_RANK CUME_DIST NTILE LAG LEAD FIRST_VALUE LAST_VALUE NTH_VALUE NUM_NONNULLS NUM_NULLS ABS CBRT CEIL CEILING DEGREES DIV EXP FLOOR LN LOG MOD PI POWER RADIANS ROUND SCALE SIGN SQRT TRUNC WIDTH_BUCKET RANDOM SETSEED ACOS ACOSD ASIN ASIND ATAN ATAND ATAN2 ATAN2D COS COSD COT COTD SIN SIND TAN TAND BIT_LENGTH CHAR_LENGTH CHARACTER_LENGTH LOWER OCTET_LENGTH OVERLAY POSITION SUBSTRING TREAT TRIM UPPER ASCII BTRIM CHR CONCAT CONCAT_WS CONVERT CONVERT_FROM CONVERT_TO DECODE ENCODE INITCAP LEFT LENGTH LPAD LTRIM MD5 PARSE_IDENT PG_CLIENT_ENCODING QUOTE_IDENT|10 QUOTE_LITERAL|10 QUOTE_NULLABLE|10 REGEXP_MATCH REGEXP_MATCHES REGEXP_REPLACE REGEXP_SPLIT_TO_ARRAY REGEXP_SPLIT_TO_TABLE REPEAT REPLACE REVERSE RIGHT RPAD RTRIM SPLIT_PART STRPOS SUBSTR TO_ASCII TO_HEX TRANSLATE OCTET_LENGTH GET_BIT GET_BYTE SET_BIT SET_BYTE TO_CHAR TO_DATE TO_NUMBER TO_TIMESTAMP AGE CLOCK_TIMESTAMP|10 DATE_PART DATE_TRUNC ISFINITE JUSTIFY_DAYS JUSTIFY_HOURS JUSTIFY_INTERVAL MAKE_DATE MAKE_INTERVAL|10 MAKE_TIME MAKE_TIMESTAMP|10 MAKE_TIMESTAMPTZ|10 NOW STATEMENT_TIMESTAMP|10 TIMEOFDAY TRANSACTION_TIMESTAMP|10 ENUM_FIRST ENUM_LAST ENUM_RANGE AREA CENTER DIAMETER HEIGHT ISCLOSED ISOPEN NPOINTS PCLOSE POPEN RADIUS WIDTH BOX BOUND_BOX CIRCLE LINE LSEG PATH POLYGON ABBREV BROADCAST HOST HOSTMASK MASKLEN NETMASK NETWORK SET_MASKLEN TEXT INET_SAME_FAMILY INET_MERGE MACADDR8_SET7BIT ARRAY_TO_TSVECTOR GET_CURRENT_TS_CONFIG NUMNODE PLAINTO_TSQUERY PHRASETO_TSQUERY WEBSEARCH_TO_TSQUERY QUERYTREE SETWEIGHT STRIP TO_TSQUERY TO_TSVECTOR JSON_TO_TSVECTOR JSONB_TO_TSVECTOR TS_DELETE TS_FILTER TS_HEADLINE TS_RANK TS_RANK_CD TS_REWRITE TSQUERY_PHRASE TSVECTOR_TO_ARRAY TSVECTOR_UPDATE_TRIGGER TSVECTOR_UPDATE_TRIGGER_COLUMN XMLCOMMENT XMLCONCAT XMLELEMENT XMLFOREST XMLPI XMLROOT XMLEXISTS XML_IS_WELL_FORMED XML_IS_WELL_FORMED_DOCUMENT XML_IS_WELL_FORMED_CONTENT XPATH XPATH_EXISTS XMLTABLE XMLNAMESPACES TABLE_TO_XML TABLE_TO_XMLSCHEMA TABLE_TO_XML_AND_XMLSCHEMA QUERY_TO_XML QUERY_TO_XMLSCHEMA QUERY_TO_XML_AND_XMLSCHEMA CURSOR_TO_XML CURSOR_TO_XMLSCHEMA SCHEMA_TO_XML SCHEMA_TO_XMLSCHEMA SCHEMA_TO_XML_AND_XMLSCHEMA DATABASE_TO_XML DATABASE_TO_XMLSCHEMA DATABASE_TO_XML_AND_XMLSCHEMA XMLATTRIBUTES TO_JSON TO_JSONB ARRAY_TO_JSON ROW_TO_JSON JSON_BUILD_ARRAY JSONB_BUILD_ARRAY JSON_BUILD_OBJECT JSONB_BUILD_OBJECT JSON_OBJECT JSONB_OBJECT JSON_ARRAY_LENGTH JSONB_ARRAY_LENGTH JSON_EACH JSONB_EACH JSON_EACH_TEXT JSONB_EACH_TEXT JSON_EXTRACT_PATH JSONB_EXTRACT_PATH JSON_OBJECT_KEYS JSONB_OBJECT_KEYS JSON_POPULATE_RECORD JSONB_POPULATE_RECORD JSON_POPULATE_RECORDSET JSONB_POPULATE_RECORDSET JSON_ARRAY_ELEMENTS JSONB_ARRAY_ELEMENTS JSON_ARRAY_ELEMENTS_TEXT JSONB_ARRAY_ELEMENTS_TEXT JSON_TYPEOF JSONB_TYPEOF JSON_TO_RECORD JSONB_TO_RECORD JSON_TO_RECORDSET JSONB_TO_RECORDSET JSON_STRIP_NULLS JSONB_STRIP_NULLS JSONB_SET JSONB_INSERT JSONB_PRETTY CURRVAL LASTVAL NEXTVAL SETVAL COALESCE NULLIF GREATEST LEAST ARRAY_APPEND ARRAY_CAT ARRAY_NDIMS ARRAY_DIMS ARRAY_FILL ARRAY_LENGTH ARRAY_LOWER ARRAY_POSITION ARRAY_POSITIONS ARRAY_PREPEND ARRAY_REMOVE ARRAY_REPLACE ARRAY_TO_STRING ARRAY_UPPER CARDINALITY STRING_TO_ARRAY UNNEST ISEMPTY LOWER_INC UPPER_INC LOWER_INF UPPER_INF RANGE_MERGE GENERATE_SERIES GENERATE_SUBSCRIPTS CURRENT_DATABASE CURRENT_QUERY CURRENT_SCHEMA|10 CURRENT_SCHEMAS|10 INET_CLIENT_ADDR INET_CLIENT_PORT INET_SERVER_ADDR INET_SERVER_PORT ROW_SECURITY_ACTIVE FORMAT_TYPE TO_REGCLASS TO_REGPROC TO_REGPROCEDURE TO_REGOPER TO_REGOPERATOR TO_REGTYPE TO_REGNAMESPACE TO_REGROLE COL_DESCRIPTION OBJ_DESCRIPTION SHOBJ_DESCRIPTION TXID_CURRENT TXID_CURRENT_IF_ASSIGNED TXID_CURRENT_SNAPSHOT TXID_SNAPSHOT_XIP TXID_SNAPSHOT_XMAX TXID_SNAPSHOT_XMIN TXID_VISIBLE_IN_SNAPSHOT TXID_STATUS CURRENT_SETTING SET_CONFIG BRIN_SUMMARIZE_NEW_VALUES BRIN_SUMMARIZE_RANGE BRIN_DESUMMARIZE_RANGE GIN_CLEAN_PENDING_LIST SUPPRESS_REDUNDANT_UPDATES_TRIGGER LO_FROM_BYTEA LO_PUT LO_GET LO_CREAT LO_CREATE LO_UNLINK LO_IMPORT LO_EXPORT LOREAD LOWRITE GROUPING CAST".split(" ").map((E=>E.split("|")[0])).join("|") 637 | ;return{name:"PostgreSQL",aliases:["postgres","postgresql"],supersetOf:"sql", 638 | case_insensitive:!0,keywords:{ 639 | keyword:"ABORT ALTER ANALYZE BEGIN CALL CHECKPOINT|10 CLOSE CLUSTER COMMENT COMMIT COPY CREATE DEALLOCATE DECLARE DELETE DISCARD DO DROP END EXECUTE EXPLAIN FETCH GRANT IMPORT INSERT LISTEN LOAD LOCK MOVE NOTIFY PREPARE REASSIGN|10 REFRESH REINDEX RELEASE RESET REVOKE ROLLBACK SAVEPOINT SECURITY SELECT SET SHOW START TRUNCATE UNLISTEN|10 UPDATE VACUUM|10 VALUES AGGREGATE COLLATION CONVERSION|10 DATABASE DEFAULT PRIVILEGES DOMAIN TRIGGER EXTENSION FOREIGN WRAPPER|10 TABLE FUNCTION GROUP LANGUAGE LARGE OBJECT MATERIALIZED VIEW OPERATOR CLASS FAMILY POLICY PUBLICATION|10 ROLE RULE SCHEMA SEQUENCE SERVER STATISTICS SUBSCRIPTION SYSTEM TABLESPACE CONFIGURATION DICTIONARY PARSER TEMPLATE TYPE USER MAPPING PREPARED ACCESS METHOD CAST AS TRANSFORM TRANSACTION OWNED TO INTO SESSION AUTHORIZATION INDEX PROCEDURE ASSERTION ALL ANALYSE AND ANY ARRAY ASC ASYMMETRIC|10 BOTH CASE CHECK COLLATE COLUMN CONCURRENTLY|10 CONSTRAINT CROSS DEFERRABLE RANGE DESC DISTINCT ELSE EXCEPT FOR FREEZE|10 FROM FULL HAVING ILIKE IN INITIALLY INNER INTERSECT IS ISNULL JOIN LATERAL LEADING LIKE LIMIT NATURAL NOT NOTNULL NULL OFFSET ON ONLY OR ORDER OUTER OVERLAPS PLACING PRIMARY REFERENCES RETURNING SIMILAR SOME SYMMETRIC TABLESAMPLE THEN TRAILING UNION UNIQUE USING VARIADIC|10 VERBOSE WHEN WHERE WINDOW WITH BY RETURNS INOUT OUT SETOF|10 IF STRICT CURRENT CONTINUE OWNER LOCATION OVER PARTITION WITHIN BETWEEN ESCAPE EXTERNAL INVOKER DEFINER WORK RENAME VERSION CONNECTION CONNECT TABLES TEMP TEMPORARY FUNCTIONS SEQUENCES TYPES SCHEMAS OPTION CASCADE RESTRICT ADD ADMIN EXISTS VALID VALIDATE ENABLE DISABLE REPLICA|10 ALWAYS PASSING COLUMNS PATH REF VALUE OVERRIDING IMMUTABLE STABLE VOLATILE BEFORE AFTER EACH ROW PROCEDURAL ROUTINE NO HANDLER VALIDATOR OPTIONS STORAGE OIDS|10 WITHOUT INHERIT DEPENDS CALLED INPUT LEAKPROOF|10 COST ROWS NOWAIT SEARCH UNTIL ENCRYPTED|10 PASSWORD CONFLICT|10 INSTEAD INHERITS CHARACTERISTICS WRITE CURSOR ALSO STATEMENT SHARE EXCLUSIVE INLINE ISOLATION REPEATABLE READ COMMITTED SERIALIZABLE UNCOMMITTED LOCAL GLOBAL SQL PROCEDURES RECURSIVE SNAPSHOT ROLLUP CUBE TRUSTED|10 INCLUDE FOLLOWING PRECEDING UNBOUNDED RANGE GROUPS UNENCRYPTED|10 SYSID FORMAT DELIMITER HEADER QUOTE ENCODING FILTER OFF FORCE_QUOTE FORCE_NOT_NULL FORCE_NULL COSTS BUFFERS TIMING SUMMARY DISABLE_PAGE_SKIPPING RESTART CYCLE GENERATED IDENTITY DEFERRED IMMEDIATE LEVEL LOGGED UNLOGGED OF NOTHING NONE EXCLUDE ATTRIBUTE USAGE ROUTINES TRUE FALSE NAN INFINITY ALIAS BEGIN CONSTANT DECLARE END EXCEPTION RETURN PERFORM|10 RAISE GET DIAGNOSTICS STACKED|10 FOREACH LOOP ELSIF EXIT WHILE REVERSE SLICE DEBUG LOG INFO NOTICE WARNING ASSERT OPEN SUPERUSER NOSUPERUSER CREATEDB NOCREATEDB CREATEROLE NOCREATEROLE INHERIT NOINHERIT LOGIN NOLOGIN REPLICATION NOREPLICATION BYPASSRLS NOBYPASSRLS ", 640 | built_in:"CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURRENT_CATALOG|10 CURRENT_DATE LOCALTIME LOCALTIMESTAMP CURRENT_ROLE|10 CURRENT_SCHEMA|10 SESSION_USER PUBLIC FOUND NEW OLD TG_NAME|10 TG_WHEN|10 TG_LEVEL|10 TG_OP|10 TG_RELID|10 TG_RELNAME|10 TG_TABLE_NAME|10 TG_TABLE_SCHEMA|10 TG_NARGS|10 TG_ARGV|10 TG_EVENT|10 TG_TAG|10 ROW_COUNT RESULT_OID|10 PG_CONTEXT|10 RETURNED_SQLSTATE COLUMN_NAME CONSTRAINT_NAME PG_DATATYPE_NAME|10 MESSAGE_TEXT TABLE_NAME SCHEMA_NAME PG_EXCEPTION_DETAIL|10 PG_EXCEPTION_HINT|10 PG_EXCEPTION_CONTEXT|10 SQLSTATE SQLERRM|10 SUCCESSFUL_COMPLETION WARNING DYNAMIC_RESULT_SETS_RETURNED IMPLICIT_ZERO_BIT_PADDING NULL_VALUE_ELIMINATED_IN_SET_FUNCTION PRIVILEGE_NOT_GRANTED PRIVILEGE_NOT_REVOKED STRING_DATA_RIGHT_TRUNCATION DEPRECATED_FEATURE NO_DATA NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED SQL_STATEMENT_NOT_YET_COMPLETE CONNECTION_EXCEPTION CONNECTION_DOES_NOT_EXIST CONNECTION_FAILURE SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION TRANSACTION_RESOLUTION_UNKNOWN PROTOCOL_VIOLATION TRIGGERED_ACTION_EXCEPTION FEATURE_NOT_SUPPORTED INVALID_TRANSACTION_INITIATION LOCATOR_EXCEPTION INVALID_LOCATOR_SPECIFICATION INVALID_GRANTOR INVALID_GRANT_OPERATION INVALID_ROLE_SPECIFICATION DIAGNOSTICS_EXCEPTION STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER CASE_NOT_FOUND CARDINALITY_VIOLATION DATA_EXCEPTION ARRAY_SUBSCRIPT_ERROR CHARACTER_NOT_IN_REPERTOIRE DATETIME_FIELD_OVERFLOW DIVISION_BY_ZERO ERROR_IN_ASSIGNMENT ESCAPE_CHARACTER_CONFLICT INDICATOR_OVERFLOW INTERVAL_FIELD_OVERFLOW INVALID_ARGUMENT_FOR_LOGARITHM INVALID_ARGUMENT_FOR_NTILE_FUNCTION INVALID_ARGUMENT_FOR_NTH_VALUE_FUNCTION INVALID_ARGUMENT_FOR_POWER_FUNCTION INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION INVALID_CHARACTER_VALUE_FOR_CAST INVALID_DATETIME_FORMAT INVALID_ESCAPE_CHARACTER INVALID_ESCAPE_OCTET INVALID_ESCAPE_SEQUENCE NONSTANDARD_USE_OF_ESCAPE_CHARACTER INVALID_INDICATOR_PARAMETER_VALUE INVALID_PARAMETER_VALUE INVALID_REGULAR_EXPRESSION INVALID_ROW_COUNT_IN_LIMIT_CLAUSE INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE INVALID_TABLESAMPLE_ARGUMENT INVALID_TABLESAMPLE_REPEAT INVALID_TIME_ZONE_DISPLACEMENT_VALUE INVALID_USE_OF_ESCAPE_CHARACTER MOST_SPECIFIC_TYPE_MISMATCH NULL_VALUE_NOT_ALLOWED NULL_VALUE_NO_INDICATOR_PARAMETER NUMERIC_VALUE_OUT_OF_RANGE SEQUENCE_GENERATOR_LIMIT_EXCEEDED STRING_DATA_LENGTH_MISMATCH STRING_DATA_RIGHT_TRUNCATION SUBSTRING_ERROR TRIM_ERROR UNTERMINATED_C_STRING ZERO_LENGTH_CHARACTER_STRING FLOATING_POINT_EXCEPTION INVALID_TEXT_REPRESENTATION INVALID_BINARY_REPRESENTATION BAD_COPY_FILE_FORMAT UNTRANSLATABLE_CHARACTER NOT_AN_XML_DOCUMENT INVALID_XML_DOCUMENT INVALID_XML_CONTENT INVALID_XML_COMMENT INVALID_XML_PROCESSING_INSTRUCTION INTEGRITY_CONSTRAINT_VIOLATION RESTRICT_VIOLATION NOT_NULL_VIOLATION FOREIGN_KEY_VIOLATION UNIQUE_VIOLATION CHECK_VIOLATION EXCLUSION_VIOLATION INVALID_CURSOR_STATE INVALID_TRANSACTION_STATE ACTIVE_SQL_TRANSACTION BRANCH_TRANSACTION_ALREADY_ACTIVE HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION READ_ONLY_SQL_TRANSACTION SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED NO_ACTIVE_SQL_TRANSACTION IN_FAILED_SQL_TRANSACTION IDLE_IN_TRANSACTION_SESSION_TIMEOUT INVALID_SQL_STATEMENT_NAME TRIGGERED_DATA_CHANGE_VIOLATION INVALID_AUTHORIZATION_SPECIFICATION INVALID_PASSWORD DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST DEPENDENT_OBJECTS_STILL_EXIST INVALID_TRANSACTION_TERMINATION SQL_ROUTINE_EXCEPTION FUNCTION_EXECUTED_NO_RETURN_STATEMENT MODIFYING_SQL_DATA_NOT_PERMITTED PROHIBITED_SQL_STATEMENT_ATTEMPTED READING_SQL_DATA_NOT_PERMITTED INVALID_CURSOR_NAME EXTERNAL_ROUTINE_EXCEPTION CONTAINING_SQL_NOT_PERMITTED MODIFYING_SQL_DATA_NOT_PERMITTED PROHIBITED_SQL_STATEMENT_ATTEMPTED READING_SQL_DATA_NOT_PERMITTED EXTERNAL_ROUTINE_INVOCATION_EXCEPTION INVALID_SQLSTATE_RETURNED NULL_VALUE_NOT_ALLOWED TRIGGER_PROTOCOL_VIOLATED SRF_PROTOCOL_VIOLATED EVENT_TRIGGER_PROTOCOL_VIOLATED SAVEPOINT_EXCEPTION INVALID_SAVEPOINT_SPECIFICATION INVALID_CATALOG_NAME INVALID_SCHEMA_NAME TRANSACTION_ROLLBACK TRANSACTION_INTEGRITY_CONSTRAINT_VIOLATION SERIALIZATION_FAILURE STATEMENT_COMPLETION_UNKNOWN DEADLOCK_DETECTED SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION SYNTAX_ERROR INSUFFICIENT_PRIVILEGE CANNOT_COERCE GROUPING_ERROR WINDOWING_ERROR INVALID_RECURSION INVALID_FOREIGN_KEY INVALID_NAME NAME_TOO_LONG RESERVED_NAME DATATYPE_MISMATCH INDETERMINATE_DATATYPE COLLATION_MISMATCH INDETERMINATE_COLLATION WRONG_OBJECT_TYPE GENERATED_ALWAYS UNDEFINED_COLUMN UNDEFINED_FUNCTION UNDEFINED_TABLE UNDEFINED_PARAMETER UNDEFINED_OBJECT DUPLICATE_COLUMN DUPLICATE_CURSOR DUPLICATE_DATABASE DUPLICATE_FUNCTION DUPLICATE_PREPARED_STATEMENT DUPLICATE_SCHEMA DUPLICATE_TABLE DUPLICATE_ALIAS DUPLICATE_OBJECT AMBIGUOUS_COLUMN AMBIGUOUS_FUNCTION AMBIGUOUS_PARAMETER AMBIGUOUS_ALIAS INVALID_COLUMN_REFERENCE INVALID_COLUMN_DEFINITION INVALID_CURSOR_DEFINITION INVALID_DATABASE_DEFINITION INVALID_FUNCTION_DEFINITION INVALID_PREPARED_STATEMENT_DEFINITION INVALID_SCHEMA_DEFINITION INVALID_TABLE_DEFINITION INVALID_OBJECT_DEFINITION WITH_CHECK_OPTION_VIOLATION INSUFFICIENT_RESOURCES DISK_FULL OUT_OF_MEMORY TOO_MANY_CONNECTIONS CONFIGURATION_LIMIT_EXCEEDED PROGRAM_LIMIT_EXCEEDED STATEMENT_TOO_COMPLEX TOO_MANY_COLUMNS TOO_MANY_ARGUMENTS OBJECT_NOT_IN_PREREQUISITE_STATE OBJECT_IN_USE CANT_CHANGE_RUNTIME_PARAM LOCK_NOT_AVAILABLE OPERATOR_INTERVENTION QUERY_CANCELED ADMIN_SHUTDOWN CRASH_SHUTDOWN CANNOT_CONNECT_NOW DATABASE_DROPPED SYSTEM_ERROR IO_ERROR UNDEFINED_FILE DUPLICATE_FILE SNAPSHOT_TOO_OLD CONFIG_FILE_ERROR LOCK_FILE_EXISTS FDW_ERROR FDW_COLUMN_NAME_NOT_FOUND FDW_DYNAMIC_PARAMETER_VALUE_NEEDED FDW_FUNCTION_SEQUENCE_ERROR FDW_INCONSISTENT_DESCRIPTOR_INFORMATION FDW_INVALID_ATTRIBUTE_VALUE FDW_INVALID_COLUMN_NAME FDW_INVALID_COLUMN_NUMBER FDW_INVALID_DATA_TYPE FDW_INVALID_DATA_TYPE_DESCRIPTORS FDW_INVALID_DESCRIPTOR_FIELD_IDENTIFIER FDW_INVALID_HANDLE FDW_INVALID_OPTION_INDEX FDW_INVALID_OPTION_NAME FDW_INVALID_STRING_LENGTH_OR_BUFFER_LENGTH FDW_INVALID_STRING_FORMAT FDW_INVALID_USE_OF_NULL_POINTER FDW_TOO_MANY_HANDLES FDW_OUT_OF_MEMORY FDW_NO_SCHEMAS FDW_OPTION_NAME_NOT_FOUND FDW_REPLY_HANDLE FDW_SCHEMA_NOT_FOUND FDW_TABLE_NOT_FOUND FDW_UNABLE_TO_CREATE_EXECUTION FDW_UNABLE_TO_CREATE_REPLY FDW_UNABLE_TO_ESTABLISH_CONNECTION PLPGSQL_ERROR RAISE_EXCEPTION NO_DATA_FOUND TOO_MANY_ROWS ASSERT_FAILURE INTERNAL_ERROR DATA_CORRUPTED INDEX_CORRUPTED " 641 | },illegal:/:==|\W\s*\(\*|(^|\s)\$[a-z]|\{\{|[a-z]:\s*$|\.\.\.|TO:|DO:/, 642 | contains:[{className:"keyword",variants:[{begin:/\bTEXT\s*SEARCH\b/},{ 643 | begin:/\b(PRIMARY|FOREIGN|FOR(\s+NO)?)\s+KEY\b/},{ 644 | begin:/\bPARALLEL\s+(UNSAFE|RESTRICTED|SAFE)\b/},{ 645 | begin:/\bSTORAGE\s+(PLAIN|EXTERNAL|EXTENDED|MAIN)\b/},{ 646 | begin:/\bMATCH\s+(FULL|PARTIAL|SIMPLE)\b/},{begin:/\bNULLS\s+(FIRST|LAST)\b/},{ 647 | begin:/\bEVENT\s+TRIGGER\b/},{begin:/\b(MAPPING|OR)\s+REPLACE\b/},{ 648 | begin:/\b(FROM|TO)\s+(PROGRAM|STDIN|STDOUT)\b/},{ 649 | begin:/\b(SHARE|EXCLUSIVE)\s+MODE\b/},{ 650 | begin:/\b(LEFT|RIGHT)\s+(OUTER\s+)?JOIN\b/},{ 651 | begin:/\b(FETCH|MOVE)\s+(NEXT|PRIOR|FIRST|LAST|ABSOLUTE|RELATIVE|FORWARD|BACKWARD)\b/ 652 | },{begin:/\bPRESERVE\s+ROWS\b/},{begin:/\bDISCARD\s+PLANS\b/},{ 653 | begin:/\bREFERENCING\s+(OLD|NEW)\b/},{begin:/\bSKIP\s+LOCKED\b/},{ 654 | begin:/\bGROUPING\s+SETS\b/},{ 655 | begin:/\b(BINARY|INSENSITIVE|SCROLL|NO\s+SCROLL)\s+(CURSOR|FOR)\b/},{ 656 | begin:/\b(WITH|WITHOUT)\s+HOLD\b/},{ 657 | begin:/\bWITH\s+(CASCADED|LOCAL)\s+CHECK\s+OPTION\b/},{ 658 | begin:/\bEXCLUDE\s+(TIES|NO\s+OTHERS)\b/},{ 659 | begin:/\bFORMAT\s+(TEXT|XML|JSON|YAML)\b/},{ 660 | begin:/\bSET\s+((SESSION|LOCAL)\s+)?NAMES\b/},{begin:/\bIS\s+(NOT\s+)?UNKNOWN\b/ 661 | },{begin:/\bSECURITY\s+LABEL\b/},{begin:/\bSTANDALONE\s+(YES|NO|NO\s+VALUE)\b/ 662 | },{begin:/\bWITH\s+(NO\s+)?DATA\b/},{begin:/\b(FOREIGN|SET)\s+DATA\b/},{ 663 | begin:/\bSET\s+(CATALOG|CONSTRAINTS)\b/},{begin:/\b(WITH|FOR)\s+ORDINALITY\b/},{ 664 | begin:/\bIS\s+(NOT\s+)?DOCUMENT\b/},{ 665 | begin:/\bXML\s+OPTION\s+(DOCUMENT|CONTENT)\b/},{ 666 | begin:/\b(STRIP|PRESERVE)\s+WHITESPACE\b/},{ 667 | begin:/\bNO\s+(ACTION|MAXVALUE|MINVALUE)\b/},{ 668 | begin:/\bPARTITION\s+BY\s+(RANGE|LIST|HASH)\b/},{begin:/\bAT\s+TIME\s+ZONE\b/},{ 669 | begin:/\bGRANTED\s+BY\b/},{begin:/\bRETURN\s+(QUERY|NEXT)\b/},{ 670 | begin:/\b(ATTACH|DETACH)\s+PARTITION\b/},{ 671 | begin:/\bFORCE\s+ROW\s+LEVEL\s+SECURITY\b/},{ 672 | begin:/\b(INCLUDING|EXCLUDING)\s+(COMMENTS|CONSTRAINTS|DEFAULTS|IDENTITY|INDEXES|STATISTICS|STORAGE|ALL)\b/ 673 | },{begin:/\bAS\s+(ASSIGNMENT|IMPLICIT|PERMISSIVE|RESTRICTIVE|ENUM|RANGE)\b/}]},{ 674 | begin:/\b(FORMAT|FAMILY|VERSION)\s*\(/},{begin:/\bINCLUDE\s*\(/, 675 | keywords:"INCLUDE"},{begin:/\bRANGE(?!\s*(BETWEEN|UNBOUNDED|CURRENT|[-0-9]+))/ 676 | },{ 677 | begin:/\b(VERSION|OWNER|TEMPLATE|TABLESPACE|CONNECTION\s+LIMIT|PROCEDURE|RESTRICT|JOIN|PARSER|COPY|START|END|COLLATION|INPUT|ANALYZE|STORAGE|LIKE|DEFAULT|DELIMITER|ENCODING|COLUMN|CONSTRAINT|TABLE|SCHEMA)\s*=/ 678 | },{begin:/\b(PG_\w+?|HAS_[A-Z_]+_PRIVILEGE)\b/,relevance:10},{ 679 | begin:/\bEXTRACT\s*\(/,end:/\bFROM\b/,returnEnd:!0,keywords:{ 680 | type:"CENTURY DAY DECADE DOW DOY EPOCH HOUR ISODOW ISOYEAR MICROSECONDS MILLENNIUM MILLISECONDS MINUTE MONTH QUARTER SECOND TIMEZONE TIMEZONE_HOUR TIMEZONE_MINUTE WEEK YEAR" 681 | }},{begin:/\b(XMLELEMENT|XMLPI)\s*\(\s*NAME/,keywords:{keyword:"NAME"}},{ 682 | begin:/\b(XMLPARSE|XMLSERIALIZE)\s*\(\s*(DOCUMENT|CONTENT)/,keywords:{ 683 | keyword:"DOCUMENT CONTENT"}},{beginKeywords:"CACHE INCREMENT MAXVALUE MINVALUE", 684 | end:E.C_NUMBER_RE,returnEnd:!0,keywords:"BY CACHE INCREMENT MAXVALUE MINVALUE" 685 | },{className:"type",begin:/\b(WITH|WITHOUT)\s+TIME\s+ZONE\b/},{className:"type", 686 | begin:/\bINTERVAL\s+(YEAR|MONTH|DAY|HOUR|MINUTE|SECOND)(\s+TO\s+(MONTH|HOUR|MINUTE|SECOND))?\b/ 687 | },{ 688 | begin:/\bRETURNS\s+(LANGUAGE_HANDLER|TRIGGER|EVENT_TRIGGER|FDW_HANDLER|INDEX_AM_HANDLER|TSM_HANDLER)\b/, 689 | keywords:{keyword:"RETURNS", 690 | type:"LANGUAGE_HANDLER TRIGGER EVENT_TRIGGER FDW_HANDLER INDEX_AM_HANDLER TSM_HANDLER" 691 | }},{begin:"\\b("+I+")\\s*\\("},{begin:"\\.("+R+")\\b"},{ 692 | begin:"\\b("+R+")\\s+PATH\\b",keywords:{keyword:"PATH", 693 | type:A.replace("PATH ","")}},{className:"type",begin:"\\b("+R+")\\b"},{ 694 | className:"string",begin:"'",end:"'",contains:[{begin:"''"}]},{ 695 | className:"string",begin:"(e|E|u&|U&)'",end:"'",contains:[{begin:"\\\\."}], 696 | relevance:10},E.END_SAME_AS_BEGIN({begin:N,end:N,contains:[{ 697 | subLanguage:["pgsql","perl","python","tcl","r","lua","java","php","ruby","bash","scheme","xml","json"], 698 | endsWithParent:!0}]}),{begin:'"',end:'"',contains:[{begin:'""'}] 699 | },E.C_NUMBER_MODE,E.C_BLOCK_COMMENT_MODE,T,{className:"meta",variants:[{ 700 | begin:"%(ROW)?TYPE",relevance:10},{begin:"\\$\\d+"},{begin:"^#\\w",end:"$"}]},{ 701 | className:"symbol",begin:"<<\\s*[a-zA-Z_][a-zA-Z_0-9$]*\\s*>>",relevance:10}]}} 702 | })();hljs.registerLanguage("pgsql",E)})();/*! `plaintext` grammar compiled for Highlight.js 11.9.0 */ 703 | (()=>{var t=(()=>{"use strict";return t=>({name:"Plain text", 704 | aliases:["text","txt"],disableAutodetect:!0})})() 705 | ;hljs.registerLanguage("plaintext",t)})();/*! `python` grammar compiled for Highlight.js 11.9.0 */ 706 | (()=>{var e=(()=>{"use strict";return e=>{ 707 | const n=e.regex,a=/[\p{XID_Start}_]\p{XID_Continue}*/u,s=["and","as","assert","async","await","break","case","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","match","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],i={ 708 | $pattern:/[A-Za-z]\w+|__\w+__/,keyword:s, 709 | built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"], 710 | literal:["__debug__","Ellipsis","False","None","NotImplemented","True"], 711 | type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"] 712 | },t={className:"meta",begin:/^(>>>|\.\.\.) /},r={className:"subst",begin:/\{/, 713 | end:/\}/,keywords:i,illegal:/#/},l={begin:/\{\{/,relevance:0},b={ 714 | className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{ 715 | begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/, 716 | contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{ 717 | begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/, 718 | contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{ 719 | begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/, 720 | contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/, 721 | end:/"""/,contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([uU]|[rR])'/,end:/'/, 722 | relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{ 723 | begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/, 724 | end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/, 725 | contains:[e.BACKSLASH_ESCAPE,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/, 726 | contains:[e.BACKSLASH_ESCAPE,l,r]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] 727 | },o="[0-9](_?[0-9])*",c=`(\\b(${o}))?\\.(${o})|\\b(${o})\\.`,d="\\b|"+s.join("|"),g={ 728 | className:"number",relevance:0,variants:[{ 729 | begin:`(\\b(${o})|(${c}))[eE][+-]?(${o})[jJ]?(?=${d})`},{begin:`(${c})[jJ]?`},{ 730 | begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${d})`},{ 731 | begin:`\\b0[bB](_?[01])+[lL]?(?=${d})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${d})` 732 | },{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${d})`},{begin:`\\b(${o})[jJ](?=${d})` 733 | }]},p={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:i, 734 | contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},m={ 735 | className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/, 736 | end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:i, 737 | contains:["self",t,g,b,e.HASH_COMMENT_MODE]}]};return r.contains=[b,g,t],{ 738 | name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:i, 739 | illegal:/(<\/|\?)|=>/,contains:[t,g,{begin:/\bself\b/},{beginKeywords:"if", 740 | relevance:0},{match:/\bor\b/,scope:"keyword"},b,p,e.HASH_COMMENT_MODE,{ 741 | match:[/\bdef/,/\s+/,a],scope:{1:"keyword",3:"title.function"},contains:[m]},{ 742 | variants:[{match:[/\bclass/,/\s+/,a,/\s*/,/\(\s*/,a,/\s*\)/]},{ 743 | match:[/\bclass/,/\s+/,a]}],scope:{1:"keyword",3:"title.class", 744 | 6:"title.class.inherited"}},{className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/, 745 | contains:[g,m,b]}]}}})();hljs.registerLanguage("python",e)})();/*! `rust` grammar compiled for Highlight.js 11.9.0 */ 746 | (()=>{var e=(()=>{"use strict";return e=>{const t=e.regex,n={ 747 | className:"title.function.invoke",relevance:0, 748 | begin:t.concat(/\b/,/(?!let|for|while|if|else|match\b)/,e.IDENT_RE,t.lookahead(/\s*\(/)) 749 | },a="([ui](8|16|32|64|128|size)|f(32|64))?",i=["drop ","Copy","Send","Sized","Sync","Drop","Fn","FnMut","FnOnce","ToOwned","Clone","Debug","PartialEq","PartialOrd","Eq","Ord","AsRef","AsMut","Into","From","Default","Iterator","Extend","IntoIterator","DoubleEndedIterator","ExactSizeIterator","SliceConcatExt","ToString","assert!","assert_eq!","bitflags!","bytes!","cfg!","col!","concat!","concat_idents!","debug_assert!","debug_assert_eq!","env!","eprintln!","panic!","file!","format!","format_args!","include_bytes!","include_str!","line!","local_data_key!","module_path!","option_env!","print!","println!","select!","stringify!","try!","unimplemented!","unreachable!","vec!","write!","writeln!","macro_rules!","assert_ne!","debug_assert_ne!"],s=["i8","i16","i32","i64","i128","isize","u8","u16","u32","u64","u128","usize","f32","f64","str","char","bool","Box","Option","Result","String","Vec"] 750 | ;return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?",type:s, 751 | keyword:["abstract","as","async","await","become","box","break","const","continue","crate","do","dyn","else","enum","extern","false","final","fn","for","if","impl","in","let","loop","macro","match","mod","move","mut","override","priv","pub","ref","return","self","Self","static","struct","super","trait","true","try","type","typeof","unsafe","unsized","use","virtual","where","while","yield"], 752 | literal:["true","false","Some","None","Ok","Err"],built_in:i},illegal:""},n]}}})() 772 | ;hljs.registerLanguage("rust",e)})();/*! `shell` grammar compiled for Highlight.js 11.9.0 */ 773 | (()=>{var s=(()=>{"use strict";return s=>({name:"Shell Session", 774 | aliases:["console","shellsession"],contains:[{className:"meta.prompt", 775 | begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{end:/[^\\](?=\s*$)/, 776 | subLanguage:"bash"}}]})})();hljs.registerLanguage("shell",s)})();/*! `sql` grammar compiled for Highlight.js 11.9.0 */ 777 | (()=>{var e=(()=>{"use strict";return e=>{ 778 | const r=e.regex,t=e.COMMENT("--","$"),n=["true","false","unknown"],a=["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],i=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],s=["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"],o=i,c=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter((e=>!i.includes(e))),l={ 779 | begin:r.concat(/\b/,r.either(...o),/\s*\(/),relevance:0,keywords:{built_in:o}} 780 | ;return{name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{ 781 | $pattern:/\b[\w\.]+/,keyword:((e,{exceptions:r,when:t}={})=>{const n=t 782 | ;return r=r||[],e.map((e=>e.match(/\|\d+$/)||r.includes(e)?e:n(e)?e+"|0":e)) 783 | })(c,{when:e=>e.length<3}),literal:n,type:a, 784 | built_in:["current_catalog","current_date","current_default_transform_group","current_path","current_role","current_schema","current_transform_group_for_type","current_user","session_user","system_time","system_user","current_time","localtime","current_timestamp","localtimestamp"] 785 | },contains:[{begin:r.either(...s),relevance:0,keywords:{$pattern:/[\w\.]+/, 786 | keyword:c.concat(s),literal:n,type:a}},{className:"type", 787 | begin:r.either("double precision","large object","with timezone","without timezone") 788 | },l,{className:"variable",begin:/@[a-z0-9][a-z0-9_]*/},{className:"string", 789 | variants:[{begin:/'/,end:/'/,contains:[{begin:/''/}]}]},{begin:/"/,end:/"/, 790 | contains:[{begin:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,{ 791 | className:"operator",begin:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/, 792 | relevance:0}]}}})();hljs.registerLanguage("sql",e)})();/*! `typescript` grammar compiled for Highlight.js 11.9.0 */ 793 | (()=>{var e=(()=>{"use strict" 794 | ;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","sessionStorage","module","global"],i=[].concat(r,t,s) 795 | ;function o(o){const l=o.regex,d=e,b={begin:/<[A-Za-z0-9\\._:-]+/, 796 | end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ 797 | const a=e[0].length+e.index,t=e.input[a] 798 | ;if("<"===t||","===t)return void n.ignoreMatch();let s 799 | ;">"===t&&(((e,{after:n})=>{const a="",$={ 845 | match:[/const|var|let/,/\s+/,d,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(B)], 846 | keywords:"async",className:{1:"keyword",3:"title.function"},contains:[R]} 847 | ;return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{ 848 | PARAMS_CONTAINS:w,CLASS_REFERENCE:k},illegal:/#(?![$_A-z])/, 849 | contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{ 850 | label:"use_strict",className:"meta",relevance:10, 851 | begin:/^\s*['"]use (strict|asm)['"]/ 852 | },o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,p,N,f,_,h,{match:/\$\d+/},y,k,{ 853 | className:"attr",begin:d+l.lookahead(":"),relevance:0},$,{ 854 | begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", 855 | keywords:"return throw case",relevance:0,contains:[h,o.REGEXP_MODE,{ 856 | className:"function",begin:B,returnBegin:!0,end:"\\s*=>",contains:[{ 857 | className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{ 858 | className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0, 859 | excludeEnd:!0,keywords:g,contains:w}]}]},{begin:/,/,relevance:0},{match:/\s+/, 860 | relevance:0},{variants:[{begin:"<>",end:""},{ 861 | match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:b.begin, 862 | "on:begin":b.isTrulyOpeningTag,end:b.end}],subLanguage:"xml",contains:[{ 863 | begin:b.begin,end:b.end,skip:!0,contains:["self"]}]}]},O,{ 864 | beginKeywords:"while if switch catch for"},{ 865 | begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", 866 | returnBegin:!0,label:"func.def",contains:[R,o.inherit(o.TITLE_MODE,{begin:d, 867 | className:"title.function"})]},{match:/\.\.\./,relevance:0},T,{match:"\\$"+d, 868 | relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, 869 | contains:[R]},C,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/, 870 | className:"variable.constant"},x,M,{match:/\$[(.]/}]}}return t=>{ 871 | const s=o(t),r=e,l=["any","void","number","boolean","string","object","never","symbol","bigint","unknown"],d={ 872 | beginKeywords:"namespace",end:/\{/,excludeEnd:!0, 873 | contains:[s.exports.CLASS_REFERENCE]},b={beginKeywords:"interface",end:/\{/, 874 | excludeEnd:!0,keywords:{keyword:"interface extends",built_in:l}, 875 | contains:[s.exports.CLASS_REFERENCE]},g={$pattern:e, 876 | keyword:n.concat(["type","namespace","interface","public","private","protected","implements","declare","abstract","readonly","enum","override"]), 877 | literal:a,built_in:i.concat(l),"variable.language":c},u={className:"meta", 878 | begin:"@"+r},m=(e,n,a)=>{const t=e.contains.findIndex((e=>e.label===n)) 879 | ;if(-1===t)throw Error("can not find mode to replace");e.contains.splice(t,1,a)} 880 | ;return Object.assign(s.keywords,g), 881 | s.exports.PARAMS_CONTAINS.push(u),s.contains=s.contains.concat([u,d,b]), 882 | m(s,"shebang",t.SHEBANG()),m(s,"use_strict",{className:"meta",relevance:10, 883 | begin:/^\s*['"]use strict['"]/ 884 | }),s.contains.find((e=>"func.def"===e.label)).relevance=0,Object.assign(s,{ 885 | name:"TypeScript",aliases:["ts","tsx","mts","cts"]}),s}})() 886 | ;hljs.registerLanguage("typescript",e)})();/*! `wasm` grammar compiled for Highlight.js 11.9.0 */ 887 | (()=>{var e=(()=>{"use strict";return e=>{e.regex;const a=e.COMMENT(/\(;/,/;\)/) 888 | ;return a.contains.push("self"),{name:"WebAssembly",keywords:{$pattern:/[\w.]+/, 889 | keyword:["anyfunc","block","br","br_if","br_table","call","call_indirect","data","drop","elem","else","end","export","func","global.get","global.set","local.get","local.set","local.tee","get_global","get_local","global","if","import","local","loop","memory","memory.grow","memory.size","module","mut","nop","offset","param","result","return","select","set_global","set_local","start","table","tee_local","then","type","unreachable"] 890 | },contains:[e.COMMENT(/;;/,/$/),a,{match:[/(?:offset|align)/,/\s*/,/=/], 891 | className:{1:"keyword",3:"operator"}},{className:"variable",begin:/\$[\w_]+/},{ 892 | match:/(\((?!;)|\))+/,className:"punctuation",relevance:0},{ 893 | begin:[/(?:func|call|call_indirect)/,/\s+/,/\$[^\s)]+/],className:{1:"keyword", 894 | 3:"title.function"}},e.QUOTE_STRING_MODE,{match:/(i32|i64|f32|f64)(?!\.)/, 895 | className:"type"},{className:"keyword", 896 | match:/\b(f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|nearest|neg?|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|store(?:8|16|32)?|sqrt|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))\b/ 897 | },{className:"number",relevance:0, 898 | match:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/ 899 | }]}}})();hljs.registerLanguage("wasm",e)})();/*! `xml` grammar compiled for Highlight.js 11.9.0 */ 900 | (()=>{var e=(()=>{"use strict";return e=>{ 901 | const a=e.regex,n=a.concat(/[\p{L}_]/u,a.optional(/[\p{L}0-9_.-]*:/u),/[\p{L}0-9_.-]*/u),s={ 902 | className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},t={begin:/\s/, 903 | contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] 904 | },i=e.inherit(t,{begin:/\(/,end:/\)/}),c=e.inherit(e.APOS_STRING_MODE,{ 905 | className:"string"}),l=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),r={ 906 | endsWithParent:!0,illegal:/`]+/}]}]}]};return{ 910 | name:"HTML, XML", 911 | aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], 912 | case_insensitive:!0,unicodeRegex:!0,contains:[{className:"meta",begin://,relevance:10,contains:[t,l,c,i,{begin:/\[/,end:/\]/,contains:[{ 914 | className:"meta",begin://,contains:[t,i,l,c]}]}] 915 | },e.COMMENT(//,{relevance:10}),{begin://, 916 | relevance:10},s,{className:"meta",end:/\?>/,variants:[{begin:/<\?xml/, 917 | relevance:10,contains:[l]},{begin:/<\?[a-z][a-z0-9]+/}]},{className:"tag", 918 | begin:/)/,end:/>/,keywords:{name:"style"},contains:[r],starts:{ 919 | end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", 920 | begin:/)/,end:/>/,keywords:{name:"script"},contains:[r],starts:{ 921 | end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ 922 | className:"tag",begin:/<>|<\/>/},{className:"tag", 923 | begin:a.concat(//,/>/,/\s/)))), 924 | end:/\/?>/,contains:[{className:"name",begin:n,relevance:0,starts:r}]},{ 925 | className:"tag",begin:a.concat(/<\//,a.lookahead(a.concat(n,/>/))),contains:[{ 926 | className:"name",begin:n,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}} 927 | })();hljs.registerLanguage("xml",e)})();/*! `yaml` grammar compiled for Highlight.js 11.9.0 */ 928 | (()=>{var e=(()=>{"use strict";return e=>{ 929 | const n="true false yes no null",a="[\\w#;/?:@&=+$,.~*'()[\\]]+",s={ 930 | className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/ 931 | },{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable", 932 | variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(s,{ 933 | variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={ 934 | end:",",endsWithParent:!0,excludeEnd:!0,keywords:n,relevance:0},t={begin:/\{/, 935 | end:/\}/,contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]", 936 | contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",variants:[{ 937 | begin:/\w[\w :()\./-]*:(?=[ \t]|$)/},{begin:/"\w[\w :()\./-]*":(?=[ \t]|$)/},{ 938 | begin:/'\w[\w :()\./-]*':(?=[ \t]|$)/}]},{className:"meta",begin:"^---\\s*$", 939 | relevance:10},{className:"string", 940 | begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{ 941 | begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0, 942 | relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type", 943 | begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a 944 | },{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta", 945 | begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)", 946 | relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{ 947 | className:"number", 948 | 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" 949 | },{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},t,g,s],r=[...b] 950 | ;return r.pop(),r.push(i),l.contains=r,{name:"YAML",case_insensitive:!0, 951 | aliases:["yml"],contains:b}}})();hljs.registerLanguage("yaml",e)})(); --------------------------------------------------------------------------------