Inline question choices, compact one-click inbox cards, drop snooze
This commit is contained in:
Vendored
+51
-10
@@ -1,4 +1,8 @@
|
||||
import { h } from "./dom.js";
|
||||
const choiceMarker = /^(\([ *]\)|\[[ xX]\])\s+(\S.*?)\s*$/;
|
||||
const detailsOpen = /^\s*<details>\s*(?:<summary>(.*?)<\/summary>)?\s*$/i;
|
||||
const summaryLine = /^\s*<summary>(.*?)<\/summary>\s*$/i;
|
||||
const detailsClose = /^\s*<\/details>\s*$/i;
|
||||
const fence = /^\s*(```|~~~)/;
|
||||
const heading = /^(#{1,6})\s+(.*)$/;
|
||||
const bullet = /^(\s*)[-*+]\s+(.*)$/;
|
||||
@@ -6,13 +10,13 @@ const ordered = /^(\s*)(\d+)[.)]\s+(.*)$/;
|
||||
const quote = /^\s*>\s?(.*)$/;
|
||||
const rule = /^\s*([-*_])(\s*\1){2,}\s*$/;
|
||||
const tableSep = /^\s*\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)*\|?\s*$/;
|
||||
export function markdown(src, className = "md") {
|
||||
return h("div", { class: className }, ...blocks(src.replace(/\r\n?/g, "\n").split("\n")));
|
||||
export function markdown(src, className = "md", choice) {
|
||||
return h("div", { class: className }, ...blocks(src.replace(/\r\n?/g, "\n").split("\n"), choice));
|
||||
}
|
||||
export function inlineMarkdown(src) {
|
||||
return h("span", { class: "md-inline" }, ...inline(src));
|
||||
}
|
||||
function blocks(lines) {
|
||||
function blocks(lines, choice) {
|
||||
const out = [];
|
||||
let i = 0;
|
||||
while (i < lines.length) {
|
||||
@@ -34,6 +38,34 @@ function blocks(lines) {
|
||||
out.push(h("pre", { class: "md-code" }, h("code", {}, body.join("\n"))));
|
||||
continue;
|
||||
}
|
||||
if (detailsClose.test(line)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
const d = detailsOpen.exec(line);
|
||||
if (d) {
|
||||
let title = d[1];
|
||||
i++;
|
||||
if (title === undefined && i < lines.length && summaryLine.test(lines[i])) {
|
||||
title = summaryLine.exec(lines[i])[1];
|
||||
i++;
|
||||
}
|
||||
const body = [];
|
||||
let depth = 1;
|
||||
while (i < lines.length) {
|
||||
const l = lines[i];
|
||||
i++;
|
||||
if (detailsOpen.test(l)) {
|
||||
depth++;
|
||||
}
|
||||
else if (detailsClose.test(l) && --depth === 0) {
|
||||
break;
|
||||
}
|
||||
body.push(l);
|
||||
}
|
||||
out.push(h("details", { class: "md-details" }, h("summary", {}, ...inline(title?.trim() || "Details")), h("div", { class: "md-details-body" }, ...blocks(body, choice))));
|
||||
continue;
|
||||
}
|
||||
const hd = heading.exec(line);
|
||||
if (hd) {
|
||||
const level = Math.min(hd[1].length + 2, 6);
|
||||
@@ -56,7 +88,7 @@ function blocks(lines) {
|
||||
continue;
|
||||
}
|
||||
if (bullet.test(line) || ordered.test(line)) {
|
||||
const [list, next] = parseList(lines, i);
|
||||
const [list, next] = parseList(lines, i, choice);
|
||||
out.push(list);
|
||||
i = next;
|
||||
continue;
|
||||
@@ -83,6 +115,8 @@ function blocks(lines) {
|
||||
function startsBlock(lines, i) {
|
||||
const line = lines[i];
|
||||
return (fence.test(line) ||
|
||||
detailsOpen.test(line) ||
|
||||
detailsClose.test(line) ||
|
||||
heading.test(line) ||
|
||||
rule.test(line) ||
|
||||
quote.test(line) ||
|
||||
@@ -103,7 +137,7 @@ function joinLines(lines) {
|
||||
function indentOf(line) {
|
||||
return line.length - line.trimStart().length;
|
||||
}
|
||||
function parseList(lines, start) {
|
||||
function parseList(lines, start, choice) {
|
||||
const first = lines[start];
|
||||
const isOrdered = !bullet.test(first);
|
||||
const base = indentOf(first);
|
||||
@@ -141,27 +175,34 @@ function parseList(lines, start) {
|
||||
body.push(indentOf(next) > base ? next.slice(Math.min(indentOf(next), base + 2)) : next.trim());
|
||||
i++;
|
||||
}
|
||||
list.append(item(body));
|
||||
list.append(item(body, isOrdered ? undefined : choice));
|
||||
while (i < lines.length && lines[i].trim() === "" && lines[i + 1] !== undefined && indentOf(lines[i + 1]) === base && (isOrdered ? ordered : bullet).test(lines[i + 1])) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return [list, i];
|
||||
}
|
||||
function item(body) {
|
||||
function item(body, choice) {
|
||||
const li = h("li");
|
||||
const m = choice && choiceMarker.exec(body[0]);
|
||||
const picker = m ? choice(m[2]) : null;
|
||||
if (picker) {
|
||||
li.className = "choice";
|
||||
li.append(picker);
|
||||
}
|
||||
const first = picker ? [] : [body[0]];
|
||||
const rest = body.slice(1);
|
||||
if (rest.every((l) => !startsBlockLine(l)) && !rest.includes("")) {
|
||||
li.append(...joinLines(body.map((l) => l.trim())));
|
||||
li.append(...joinLines([...first, ...rest].map((l) => l.trim())));
|
||||
return li;
|
||||
}
|
||||
const head = [body[0]];
|
||||
const head = first;
|
||||
let k = 1;
|
||||
while (k < body.length && body[k] !== "" && !startsBlockLine(body[k])) {
|
||||
head.push(body[k].trim());
|
||||
k++;
|
||||
}
|
||||
li.append(...joinLines(head), ...blocks(body.slice(k)));
|
||||
li.append(...joinLines(head), ...blocks(body.slice(k), choice));
|
||||
return li;
|
||||
}
|
||||
function startsBlockLine(line) {
|
||||
|
||||
Reference in New Issue
Block a user