this repo has no description

new table dividers, fix `` parsing

12Me21 62b1cd34 f4677d09

+138 -76
+87 -64
markup.css
··· 15 15 16 16 *:not(*>*) { /* this selects :root with 0 specificity */ 17 17 /* normal colors */ 18 - --T-color: black; 19 18 --T-bg: white; 20 19 21 20 --T-link-color: #056; ··· 24 23 --T-custom-link-decoration: underline blue; 25 24 26 25 --T-border-color: gray; /* nnnnn... */ 27 - /* these are transparent, so they should work with both dark and light */ 26 + 28 27 --T-image-border: 1px solid var(--T-border-color); 29 28 30 - --T-box-bg: #AAA2; 29 + --T-embed-height: 10vh; 31 30 32 - --T-red-bg: #F888; 33 - --T-green-bg: #FA08; 34 - --T-yellow-bg: #FF08; 35 - --T-orange-bg: #0F08; 36 - --T-blue-bg: #08F8; 37 - --T-purple-bg: #C0F8; 38 - --T-gray-bg: #AAA8; 39 - 40 - --T-link-bg: #5CE5; /* for links w/ custom text */ 31 + /* for colored table cells, etc. */ 32 + /* these are transparent, so they should work with both dark and light */ 33 + 888; 34 + #0F08; 35 + #FF08; 36 + #FA08; 37 + 08F8; 38 + #C0F8; 39 + AAA8; 41 40 42 - 43 - --T-tab-size: 2.5; 44 - --T-embed-height: 10vh; 41 + --T-box-bg: #AAA2; 45 42 46 - --T-font: 1em sans-serif; 47 - --T-monospace-font: 0.8128em consolas, monospace; 43 + /* other values used : 44 + --T-tab-size 45 + --T-monospace-font 46 + 47 + --T-table-border 48 + --T-table-outer-border 49 + --T-table-thick-border 50 + 51 + --T-code-color 52 + --T-code-bg 53 + 54 + --T-red-bg: 55 + --T-green-bg: 56 + --T-yellow-bg: 57 + --T-orange-bg: 58 + --T-blue-bg: 59 + --T-purple-bg: 60 + --T-gray-bg: 61 + */ 48 62 } 49 63 50 64 /** aa */ 51 65 52 66 .Markup { 53 - color: var(--T-color); 54 67 background: var(--T-bg); 55 - font: var(--T-font); /* this is kinda bad.. maybe there should be a --T-markup-font ? or something separate for the main site and markup. then you can set --T-markup-font to "inherit" */ 68 + font-family: inherit; 56 69 font-variant-ligatures: none; 57 - -moz-tab-size: var(--T-tab-size); 58 - tab-size: var(--T-tab-size); 70 + -moz-tab-size: var(--T-tab-size, 2.5); tab-size: var(--T-tab-size, 2.5); 59 71 } 60 72 61 73 .Markup * { ··· 108 120 .Markup img[data-state="loaded"] { 109 121 height: auto; 110 122 } 111 - .Markup img[data-state="size"] { 112 - } 113 123 114 124 /* ruby text doesn't work if set to white-space: pre */ 115 125 .Markup rt { ··· 121 131 background: #F888; 122 132 } 123 133 124 - /*** keyboard key ***/ 125 - .Markup kbd { 126 - display: inline-block; 127 - 128 - background: var(--T-box-bg); 129 - border: 1px solid var(--T-border-color); 130 - border-radius: 3px; 131 - padding: 0.1875rem 0.375rem; 132 - font: var(--T-monospace-font); 133 - vertical-align: middle; 134 - } 135 - 136 134 /*** divider ***/ 137 135 .Markup hr { 138 136 margin: 0.5rem 0; 139 137 } 140 138 141 - /**********/ 142 - /** Code **/ 143 - /**********/ 144 - .Markup pre, .Markup code { 145 - font: var(--T-monospace-font); 139 + .Markup pre, .Markup code, .Markup kbd { 140 + font-family: var(--T-monospace-font, "Cascadia Code", consolas, monospace); 141 + font-size: 0.8125em; 146 142 } 147 - /* inline */ 143 + /*** Inline Code ***/ 144 + /*** ` ***/ 148 145 .Markup code { 149 146 line-break: anywhere; 150 - vertical-align: 1px; 151 - background: #9996; 147 + background: #9995; 152 148 padding: 0 0.1875em; 153 149 border-radius: 4px; 154 150 margin: 0 0.1em; 151 + vertical-align: 1px; 155 152 } 156 - /* block */ 153 + .Markup th code { 154 + white-space: pre-wrap; 155 + line-break: unset; 156 + word-break: normal; overflow-wrap: break-word; 157 + } 158 + /*** Code Block ***/ 159 + /*** ``` ***/ 157 160 .Markup pre { 158 - color: white; 159 - background: black; 161 + color: var(--T-code-color, white); 162 + background: var(--T-code-bg, black); 160 163 border: 1px solid black; 161 164 padding: 0.5em; 162 165 margin: 0.25em 0; 163 166 line-break: anywhere; 164 167 } 168 + /*** Keyboard Key ***/ 169 + /*** \kbd ***/ 170 + .Markup kbd { 171 + display: inline-block; 172 + 173 + background: var(--T-box-bg); 174 + border: 1px solid var(--T-border-color); 175 + border-radius: 3px; 176 + padding: 0.1875rem 0.375rem; 177 + vertical-align: middle; 178 + } 165 179 166 - /*************/ 167 - /** Spoiler **/ 168 - /*************/ 180 + /*** Spoiler ***/ 181 + /*** \spoiler \h ***/ 169 182 .M-spoiler-label { 170 183 display: table; /* width... */ 171 184 background: var(--T-box-bg); ··· 224 237 .M-table-outer { 225 238 overflow-x: auto; 226 239 } 227 - .Markup table, .Markup td, .Markup th { 228 - border: 1px solid var(--T-color); 240 + .Markup table, .Markup tr > * { 229 241 border-collapse: collapse; 230 242 } 231 - .Markup td, .Markup th { 243 + .Markup table { 244 + border: var(--T-table-outer-border, 3px solid #222); 245 + } 246 + .Markup tr > * { 232 247 padding: 0.1875em 0.3125em; 233 248 /* alternate text wrap mode, produces better table widths (somewhat) */ 234 249 word-break: normal; overflow-wrap: break-word; 250 + border: var(--T-table-border, 1px solid #222); 251 + } 252 + .Markup tr > .M-wall-top { 253 + border-top: var(--T-table-thick-border, 4px solid #222); 254 + } 255 + .Markup tr > .M-wall-right { 256 + border-right: var(--T-table-thick-border, 4px solid #222); 235 257 } 236 258 237 259 /**********************/ 238 260 /** Background Color **/ 239 261 /**********************/ 240 - .Markup [data-bgcolor="red"] { background: var(--T-red-bg) } 241 - .Markup [data-bgcolor="orange"] { background: var(--T-orange-bg) } 242 - .Markup [data-bgcolor="yellow"] { background: var(--T-yellow-bg) } 243 - .Markup [data-bgcolor="green"] { background: var(--T-green-bg) } 244 - .Markup [data-bgcolor="blue"] { background: var(--T-blue-bg) } 245 - .Markup [data-bgcolor="purple"] { background: var(--T-purple-bg) } 246 - .Markup [data-bgcolor="gray"] { background: var(--T-gray-bg) } 262 + .Markup [data-bgcolor="red"] { background: var(--T-red-bg, #F888) } 263 + .Markup [data-bgcolor="orange"] { background: var(--T-orange-bg, #FA08) } 264 + .Markup [data-bgcolor="yellow"] { background: var(--T-yellow-bg, #FF08) } 265 + .Markup [data-bgcolor="green"] { background: var(--T-green-bg, #0F08) } 266 + .Markup [data-bgcolor="blue"] { background: var(--T-blue-bg, #08F8) } 267 + .Markup [data-bgcolor="purple"] { background: var(--T-purple-bg, #C0F8) } 268 + .Markup [data-bgcolor="gray"] { background: var(--T-gray-bg, #AAA8) } 247 269 .Markup table { background: var(--T-bg); } /* reset */ 248 270 249 271 /***********/ 250 272 /** Links **/ 251 273 /***********/ 252 274 .M-link { 253 - color: var(--T-link-color); 254 - text-decoration: var(--T-link-decoration); 255 - -webkit-text-decoration: var(--T-link-decoration); 275 + color: var(--T-link-color, #056); 276 + text-decoration: underline; 277 + text-decoration: var(--T-link-decoration, underline #AAAA); 278 + -webkit-text-decoration: var(--T-link-decoration, underline #AAAA); 256 279 } 257 280 .M-link:hover { 258 281 color: var(--T-link-hover-color); ··· 281 304 padding-left: 1em; 282 305 } 283 306 284 - .Markup li:last-child { 285 - margin-bottom: 0.25em; 307 + .Markup li { 308 + margin: 0.25em 0; 286 309 } 287 310 288 311 /*************/
+45 -11
parse.js
··· 41 41 `{BOL}[\`]{3}(?!.*?[\`])${'CODE_BLOCK'}` 42 42 `[\`][^\`\n]*([\`]{2}[^\`\n]*)*[\`]?${'INLINE_CODE'}` 43 43 `([!]${'EMBED'})?\b(https?://|sbs:){URL_CHARS}{URL_FINAL}([(]{URL_CHARS}[)]({URL_CHARS}{URL_FINAL})?)?${'LINK'}` 44 + `{BOL}[|][-][-+]*[-][|]{EOL}${'TABLE_DIVIDER'}` // `{BOL}[|][|][|]{EOL}${'TABLE_DIVIDER'}` 44 45 `{BOL} *[|]${'TABLE_START'}` 45 - ` *[|]${'TABLE_CELL'}` 46 + ` *[|][|]?${'TABLE_CELL'}` 46 47 `{BOL} *[-]${'LIST_ITEM'}` 47 48 () 48 49 ··· 56 57 // creates 2 cells, with 2 lines each, rather than 2 rows. 57 58 // i.e: each added row will just append its contents to the cells 58 59 // of the previous row. 60 + // maybe this should be an arg instead? on a row, to merge it with prev or etc.. 59 61 60 62 61 63 // all state is stored in these vars (and REGEX.lastIndex) ··· 63 65 64 66 // About __proto__ in object literals: 65 67 // https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-runtime-semantics-propertydefinitionevaluation 66 - const IS_BLOCK = {__proto__:null, code:1, divider:1, ROOT:1, heading:1, quote:1, table:1, table_cell:1, image:1, video:1, audio:1, spoiler:1, align:1, list:1, list_item:1, youtube:1, anchor:1} 68 + const IS_BLOCK = {__proto__:null, code:1, divider:1, ROOT:1, heading:1, quote:1, table:1, table_cell:1, image:1, video:1, audio:1, spoiler:1, align:1, list:1, list_item:1, youtube:1, anchor:1, table_divider:1} 67 69 68 70 69 71 // argument processing // ··· 132 134 let m 133 135 if ("*"===arg || "#"===arg) 134 136 args.header = true 137 + else if ("-div"===arg) 138 + args.div = true 135 139 else if (is_color(arg)) 136 140 args.color = arg 137 141 else if (m = /^(\d*)x(\d*)$/.exec(arg)) { ··· 194 198 } 195 199 } break; case 'null_env': { 196 200 current.content.push(...o.content) 201 + } break; case 'table_divider': { 202 + let above = get_last(current) 203 + if (above && 'table'===above.type) { 204 + above.args = {divider:true} 205 + } 197 206 } break; case 'table_cell': { 198 207 // push cell if not empty 199 208 if (!cancel || o.content.length) { ··· 234 243 push(dest, type, null, o.content) 235 244 } break; case 'table_row': { 236 245 let dest = get_last(current) 237 - if (!dest || 'table'!==dest.type) 246 + if (!dest || 'table'!==dest.type) { 238 247 dest = push(current, 'table', null, []) 248 + } else { 249 + if (dest.args && dest.args.divider) { 250 + delete dest.args.divider 251 + o.args.divider = true 252 + } 253 + } 239 254 push(dest, type, o.args, o.content) 240 255 } } 241 256 ··· 269 284 // parsing // 270 285 271 286 const STYLE_START 272 - = /^[\s][^\s,]|^['"}{(>][^\s,'"]/ 287 + = /^[\s][^\s,]|^['"}{(>|][^\s,'"]/ 273 288 const STYLE_END 274 - = /^[^\s,][-\s.,:;!?'"}{)<\\]/ 289 + = /^[^\s,][-\s.,:;!?'"}{)<\\|]/ 275 290 const ITALIC_START 276 - = /^[\s][^\s,/]|^['"}{(>][^\s,'"/]/ 291 + = /^[\s][^\s,/]|^['"}{(>|][^\s,'"/]/ 277 292 const ITALIC_END 278 - = /^[^\s,/][-\s.,:;!?'"}{)<\\]/ 293 + = /^[^\s,/][-\s.,:;!?'"}{)<\\|]/ 279 294 280 295 const find_style=(token)=>{ 281 296 for (let c=current; 'style'===c.type; c=c.parent) ··· 366 381 367 382 let match 368 383 let last = REGEX.lastIndex = 0 369 - const NEVERMIND=()=>{ 370 - REGEX.lastIndex = match.index+1 384 + const NEVERMIND=(index=match.index+1)=>{ 385 + REGEX.lastIndex = index 371 386 } 372 387 const ACCEPT=()=>{ 373 388 TEXT(text.substring(last, match.index)) ··· 493 508 while (current!==c) 494 509 CLOSE(true) 495 510 CLOSE() // cell 511 + // TODO: HACK 512 + if (/^ *[|][|]/.test(token)) { 513 + let last = current.content[current.content.length-1] 514 + last.args.div = true 515 + } 496 516 // we don't know whether these are row args or cell args, 497 517 // so just pass the raw args directly, and parse them later. 498 518 OPEN('table_cell', rargs) 499 519 break 500 520 } 501 521 if ('style'!==c.type) { 502 - NEVERMIND() 522 + // normally NEVERMIND skips one char, 523 + // e.g. if we parse "abc" and that matches but gets rejected, it'll try parsing at "bc". 524 + // but table cell tokens can look like this: " ||" 525 + // if we skip 1 char (a space), it would try to parse a table cell again several times. 526 + // so instead we skip to the end of the token because we know it's safe in this case. 527 + NEVERMIND(REGEX.lastIndex) 503 528 continue main 504 529 } 505 530 } 531 + } break; case 'TABLE_DIVIDER': { 532 + //skip_spaces() 533 + let tbl = get_last(current) 534 + if (!tbl || 'table'!==tbl.type) { 535 + NEVERMIND() 536 + continue main 537 + } 538 + ACCEPT() 539 + OPEN('table_divider') 506 540 } break; case 'TABLE_START': { 507 541 read_args() 508 542 skip_spaces() ··· 578 612 BLOCK('code', {text:code, lang}) 579 613 } break; case 'INLINE_CODE': { 580 614 ACCEPT() 581 - BLOCK('icode', {text: token.replace(/`(`)?/g, "$1")}) 615 + BLOCK('icode', {text: token.replace(/^`|`$/g, "").replace(/``/g, "`")}) 582 616 } break; case 'EMBED': { 583 617 read_args() 584 618 ACCEPT()
+6 -1
render.js
··· 251 251 252 252 table_row: 𐀶`<tr>`, 253 253 254 - table_cell: function({header, color, truecolor, colspan, rowspan, align}, row_args) { 254 + table_cell: function({header, color, truecolor, colspan, rowspan, align, div}, row_args) { 255 255 let e = this[header||row_args.header ? 1 : 0]() 256 256 if (color) e.dataset.bgcolor = color 257 257 if (truecolor) e.style.backgroundColor = truecolor 258 258 if (colspan) e.colSpan = colspan 259 259 if (rowspan) e.rowSpan = rowspan 260 260 if (align) e.style.textAlign = align 261 + // todo: better way of representing this? 262 + if (div) 263 + e.classList.add('M-wall-right') 264 + if (row_args.divider) 265 + e.classList.add('M-wall-top') 261 266 return e 262 267 }.bind([𐀶`<td>`, 𐀶`<th>`]), 263 268