ufh/docs/document.ts

97 lines
4.1 KiB
TypeScript

/*
# documents
Documents have block level elements (in json) and inline text (in a
custom latex-like format)
*/
type Document = DocBlock | Array<DocBlock>;
type DocBlock = DocInline
| { type: "code", content: DocInline, lang?: string }
| { type: "quote", content: Document, attr?: string }
| { type: "table", headers?: Array<DocInline>, rows: Array<Array<DocInline>> }
| { type: "ol", items: Array<Document> }
| { type: "ul", items: Array<Document> }
| { type: "details", summary: DocInline, content: Document } // maybe merge with "callout"?
| { type: "callout", call: CalloutType, content: Document }
| { type: "header", content: DocInline, level: number }
| { type: "embed", ref: string };
type CalloutType =
"section" // not highlighted but visually separated
| "info" // something noteworthy
| "warning" // something potentially dangerous if ignored
| "critical"; // something noteworthy and important
type DocInline = string;
/*
Inline text format
example: `hello ~bold{world}` = markdown `hello **world**`
in the format `~tag{arg1}{arg2}{...args}`
- escape tilde with a second tilde (eg. `~~`)
- no spaces/extra chars between `~`, tags, and arg blocks
- tags match /[a-z0-9-]+/i (that's regex a-z, A-Z, 0-9, and hyphen -)
- args can be nested (`~bold{~italic{text}}`)
handling malformed text
- append closing brackets `}` at the end of an inline string to match braces
- `~tag` followed by anything besides `{` causes the `~tag` to be interpreted literally
- extra args are ignored, missing/optional args are null, null is rendered to an empty string ("") if not handled
*/
// defined tags
// (underline is specifically not included)
// there's a lot of tags already, but i don't want a lot of tags. it
// complicates implementations for dimishing returns. right now, i'm
// trying to find a good weight/use ratio.
type Tags = {
bold: (text: string) => string,
italic: (text: string) => string,
strike: (text: string) => string,
sub: (text: string) => string, // may remove: use `math` tag instead
sup: (text: string) => string, // may remove: use `math` tag instead
del: (text: string) => string, // may remove: little to no use outside of version control and may conflict document diff semantics
ins: (text: string) => string, // may remove: same as del
color: (text: string, color: string) => string,
bgcolor: (text: string, color: string) => string,
code: (text: string, lang?: string) => string,
spoiler: (text: string, reason?: string) => string,
kbd: (keycodes: string) => string,
abbr: (short: string, description: string) => string, // may remove: probably better to have a more general "title text" tag
time: (text: string, time: Date) => string,
// these ones are questionable and may be removed - they add potentially unneeded complexity
"inline-note": (text: string, note: string) => string, // may remove: only needed for one niche use case currently
"block-note": (text: string, note: string) => string, // has potential
}
/*
## potential tags in the future:
- <dl>, <dt>, and <dd>: like ol/ul but defines several terms. maybe
useful and has nice semantics, but a table or other list already is
already pretty good and is more flexible.
- some kind of scripting: yes, <script> in its current form is awful
and too easily abusable. but i've seen enough sites that make *really
good* use of scripting that i'm not sure. general purpose scripting
almost definitely won't exist[1]
- interactive canvases: on the other hand, canvases might! this wouldn't
be its own tag, but could be its own thing, able to be embedded
in documents.
- <form>/<input>: ask people for structured input to create
an event. or forms that don't create any events, but are for calculating
things. like "interactive canvases", these probably would be their
own thing (but would be embeddable)
[1]: most pages are either completely static or webapps,
but i really think interactive documents could be really
good, see https://ciechanow.ski/mechanical-watch/ and
https://samwho.dev/memory-allocation/. these mostly fall into the
category of "static page with interactive canvas" though.
*/