diff --git a/scripts/convert_typedoc_metadata.js b/scripts/convert_typedoc_metadata.js index 4aa9289a..4e3b8212 100644 --- a/scripts/convert_typedoc_metadata.js +++ b/scripts/convert_typedoc_metadata.js @@ -32,6 +32,25 @@ function convertMetadata(project) { .map(part => part.text || "") .join("") .replace(/\n+$/, "") + const argFlags = comment => { + const flags = {} + for (const tag of comment?.blockTags || []) { + if (tag.tag !== "@flag") continue + const text = (tag.content || []) + .map(part => part.text || "") + .join("") + const flagText = text.split(/\r?\n[ \t]*\r?\n/, 1)[0] + const m = /^(-\S+)[ \t]+([^\n]+)\n*([\s\S]*)$/.exec(flagText.trim()) + if (!m) continue + const [, flag, short, rest] = m + const elaboration = rest.trim() + flags[flag] = { + short, + description: elaboration ? `${short}\n\n${elaboration}` : short, + } + } + return flags + } const normalizeParameter = (parameter, resolving) => ({ name: parameter.name, @@ -152,15 +171,16 @@ function convertMetadata(project) { .filter(node => node.kind === KIND.Function) .map(node => { const signature = node.signatures?.[0] + const comment = signature?.comment || node.comment + const flags = argFlags(comment) return [ node.name, { - doc: - commentText(signature?.comment) || - commentText(node.comment), + doc: commentText(comment), params: (signature?.parameters || []).map(parameter => normalizeParameter(parameter), ), + ...(Object.keys(flags).length ? { flags } : {}), }, ] }), diff --git a/scripts/typedoc-theme.mjs b/scripts/typedoc-theme.mjs index efcc2c3a..790efa43 100644 --- a/scripts/typedoc-theme.mjs +++ b/scripts/typedoc-theme.mjs @@ -48,8 +48,7 @@ function rewriteWikiLinks(parts, owner, reflections) { candidate => !candidate.kindOf( ReflectionKind.Module | ReflectionKind.Namespace, - ) && - !candidate.sources?.some(isGeneratedSource), + ) && !candidate.sources?.some(isGeneratedSource), ) || candidates.find( candidate => @@ -252,7 +251,91 @@ class TridactylRouter extends KindRouter { } } +function parseFlagTag(tag) { + const parts = tag.content || [] + let text = "" + let trailing = [] + for (let i = 0; i < parts.length; i++) { + const part = parts[i] + const match = part.kind === "text" && /\r?\n[ \t]*\r?\n/.exec(part.text) + if (!match) { + text += part.text || "" + continue + } + text += part.text.slice(0, match.index) + trailing = [ + { + ...part, + text: part.text.slice(match.index + match[0].length), + }, + ...parts.slice(i + 1), + ] + break + } + const m = /^(-\S+)[ \t]+([^\n]+)\n*([\s\S]*)$/.exec(text.trim()) + if (!m) return undefined + const [, flag, short, rest] = m + const elaboration = rest.trim() + return [flag, short, elaboration, trailing] +} + +function renderFlagList(context, parsed) { + if (parsed.length === 0) return null + return h( + "ul", + { class: "tsd-tag-flag tsd-parameter-list" }, + parsed.map(([flag, short, elaboration]) => + h( + "li", + null, + h("code", null, flag), + " ", + short, + elaboration && + context.displayParts([{ kind: "text", text: elaboration }]), + ), + ), + ) +} + class TridactylTheme extends DefaultTheme { + getRenderContext(page) { + const context = super.getRenderContext(page) + const defaultCommentSummary = context.commentSummary + context.commentSummary = props => { + const blockTags = props.comment?.blockTags || [] + if (!blockTags.some(tag => tag.tag === "@flag")) + return defaultCommentSummary(props) + + const summaryHeadingCount = page.pageHeadings.length + const nodes = [context.displayParts(props.comment?.summary || [])] + page.pageHeadings.length = summaryHeadingCount + let flagRun = [] + const flushFlags = () => { + if (flagRun.length === 0) return + nodes.push(renderFlagList(context, flagRun)) + flagRun = [] + } + for (const tag of blockTags) { + if (tag.tag === "@flag") { + tag.skipRendering = true + const parsed = parseFlagTag(tag) + if (!parsed) continue + const [flag, short, elaboration, trailing] = parsed + flagRun.push([flag, short, elaboration]) + if (trailing.length === 0) continue + flushFlags() + const headingCount = page.pageHeadings.length + nodes.push(context.displayParts(trailing)) + page.pageHeadings.length = headingCount + } + } + flushFlags() + return h(JSX.Fragment, null, ...nodes) + } + return context + } + getReflectionClasses(reflection) { const kind = ReflectionKind.classString(reflection.kind) const parent = @@ -335,7 +418,10 @@ class TridactylTheme extends DefaultTheme { h( "ul", null, - docLink("Commands", "modules/_src_excmds_.html"), + docLink( + "Commands", + "modules/_src_excmds_.html", + ), docLink( "Settings", "classes/_src_lib_config_.default_config.html", diff --git a/src/excmds.ts b/src/excmds.ts index 0c497392..b0cb8933 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -5526,68 +5526,83 @@ const KILL_STACK: Element[] = [] /** * Hint a page. * - * @param args Arguments to the `:hint` command. Multiple flags can be combined as long as they don't conflict. + * Multiple flags can be used in the `:hint` command and combined as long as they don't conflict. * Selectors can be specified either standalone (without a flag preceding them) or with the `-c` option. Arguments that * take callbacks (`-F` or `-W`) should be specified last, as they consume the rest of the command line. * - * Hinting action flags (only one can be specified): + * #### Hinting action flags (only one can be specified): * - * - -t open in a new foreground tab - * - -b open in background - * - -y copy (yank) link's target to clipboard - * - -p copy an element's text to the clipboard - * - -h select an element (as if you click-n-dragged over it) - * - -P copy an element's title/alt text to the clipboard - * - -r read an element's text with text-to-speech - * - -i view an image - * - -I view an image in a new tab - * - -k irreversibly deletes an element from the page (until reload) - * - -K hides an element on the page; hidden elements can be restored using [[elementunhide]]. - * - -s save (download) the linked resource - * - -S save the linked image - * - -a save-as the linked resource - * - -A save-as the linked image - * - -; focus an element and set it as the element or the child of the element to scroll - * - -# yank an element's anchor URL to clipboard - * - -w open in new window - * - -wp open in new private window - * - -z scroll an element to the top of the viewport - * - `-pipe selector key` e.g, `-pipe a href` returns the URL of the chosen link on a page. Only makes sense with `composite`, e.g, `composite hint -pipe .some-class>a textContent | yank`. If you don't select a hint (i.e. press ``), will return an empty string. Most useful when used like `-c` to do things other than opening links. NB: the query selector cannot contain any spaces. - * - `-W excmd...` pass hint href as the final argument to excmd and execute, e.g, `hint -W mpvsafe` to open YouTube videos. NB: passing it to bare [[exclaim]] is dangerous - see `get exaliases.mpvsafe` for an example of how to do it safely. The usual [[composite]] caveats for `;` and `|` in URLs apply. If you need to use a query selector, use `-pipe` instead. - * - -F [callback] - run a custom callback on the selected hint, e.g. `hint -JF e => {tri.excmds.tabopen("-b",e.href); e.remove()}`. + * @flag -t open in a new foreground tab + * @flag -b open in background + * @flag -y copy (yank) link's target to clipboard + * @flag -p copy an element's text to the clipboard + * @flag -h select an element (as if you click-n-dragged over it) + * @flag -P copy an element's title/alt text to the clipboard + * @flag -r read an element's text with text-to-speech + * @flag -i view an image + * @flag -I view an image in a new tab + * @flag -k irreversibly deletes an element from the page (until reload) + * @flag -K hides an element on the page + * - Hidden elements can be restored using [[elementunhide]]. + * @flag -s save (download) the linked resource + * @flag -S save the linked image + * @flag -a save-as the linked resource + * @flag -A save-as the linked image + * @flag -; focus an element and set it as the element or the child of the element to scroll + * @flag -# yank an element's anchor URL to clipboard + * @flag -w open in new window + * @flag -wp open in new private window + * @flag -z scroll an element to the top of the viewport + * @flag -pipe `selector key`, e.g, `-pipe a href` returns the URL of the chosen link on a page. + * - Only makes sense with `composite`, e.g, `composite hint -pipe .some-class>a textContent | yank`. + * - If you don't select a hint (i.e. press ``), will return an empty string. + * - Most useful when used like `-c` to do things other than opening links. + * - NB: the query selector cannot contain any spaces. + * @flag -W `excmd...` pass hint href as the final argument to excmd and execute. + * - e.g, `hint -W mpvsafe` to open YouTube videos. + * - NB: passing it to bare [[exclaim]] is dangerous - see `get exaliases.mpvsafe` for an example of how to do it safely. + * - The usual [[composite]] caveats for `;` and `|` in URLs apply. + * - If you need to use a query selector, use `-pipe` instead. + * @flag -F [callback] - run a custom callback on the selected hint + * - e.g. `hint -JF e => {tri.excmds.tabopen("-b",e.href); e.remove()}`. * - * Element selection flags: + * #### Element selection flags * - * - -c [selector] hint links that match the css selector - * - `bind ;c hint -c [class*="expand"],[class*="togg"]` works particularly well on reddit and HN - * - this works with most other hint modes, with the caveat that if other hint mode takes arguments your selector must contain no spaces, i.e. `hint -c[yourOtherFlag] [selector] [your other flag's arguments, which may contain spaces]` - * - -C [selector] like `-c [selector]` but also hints all elements that would normally be hinted given the other options selected - * - -x [selector] exclude the matched elements from hinting - * - -f [text] hint links and inputs that display the given text - * - `bind hint -f Edit` - * - Backslashes can escape spaces: `bind hint -f Save\ as` - * - -fr [text] use RegExp to hint the links and inputs - * - -J* disable javascript hints. Don't generate hints related to javascript events. This is particularly useful when used with the `-c` option when you want to generate only hints for the specified css selectors. Also useful on sites with plenty of useless javascript elements such as google.com - * - -V create hints for invisible elements. By default, elements outside the viewport when calling :hint are not hinted, this includes them anyways. + * @flag -c hint links that match the css selector + * - `bind ;c hint -c [class*="expand"],[class*="togg"]` works particularly well on reddit and HN. + * - This works with most other hint modes, with the caveat that if other hint mode takes arguments your selector must contain no spaces, i.e. `hint -c[yourOtherFlag] [selector] [your other flag's arguments, which may contain spaces]` + * @flag -C like -c but also hints all elements that would normally be hinted given the other options selected + * @flag -x exclude the matched elements from hinting + * @flag -f hint links and inputs that display the given text + * - `bind hint -f Edit`. + * - Backslashes can escape spaces: `bind hint -f Save\ as` + * @flag -fr use RegExp to hint the links and inputs + * @flag -J disable javascript hints + * - Don't generate hints related to javascript events. This is particularly useful when used with the `-c` option when you want to generate only hints for the specified css selectors. + * - Also useful on sites with plenty of useless javascript elements such as google.com + * @flag -V create hints for invisible elements + * - By default, elements outside the viewport when calling :hint are not hinted; this includes them anyways. * - * Hinting mode selection: + * #### Hinting mode selection: * * - -q* quick (or rapid) hints mode. Stay in hint mode until you press ``, e.g. `:hint -qb` to open multiple hints in the background or `:hint -qW excmd` to execute excmd once for each hint. This will return an array containing all elements or the result of executed functions (e.g. `hint -qpipe a href` will return an array of links). * - For example, use `bind ;jg hint -Jc .rc > .r > a` on google.com to generate hints only for clickable search results of a given query * - -! execute all hints without waiting for a selection * - For example, `hint -!bf Comments` opens in background tabs all visible links whose text matches `Comments` * - * Deprecated options: + * #### Deprecated options: * * - -br deprecated, use `-qb` instead * + * #### Usage: + * * Excepting the custom selector mode, background hint mode and the "immediate" modifier, each of these hint modes is available by default as `;