mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-14 21:32:40 +00:00
* fix(plugins): restrict overview content to safe Markdown and HTTPS destinations Registry overviews are author-controlled content read away from their repositories. Apply a shared presentation policy instead of the documentation renderer so relative links, non-HTTPS URLs, raw HTML, and author styles never become active overview content. * fix(plugins): choose the first allowed screenshot for previews
50 lines
1.2 KiB
TypeScript
50 lines
1.2 KiB
TypeScript
/** Presentation contract for author-controlled registry content, independent of the UI runtime. */
|
|
export const pluginOverviewPolicy = {
|
|
rawHtml: false,
|
|
elements: [
|
|
"p",
|
|
"br",
|
|
"hr",
|
|
"h1",
|
|
"h2",
|
|
"h3",
|
|
"h4",
|
|
"h5",
|
|
"h6",
|
|
"blockquote",
|
|
"ul",
|
|
"ol",
|
|
"li",
|
|
"strong",
|
|
"em",
|
|
"del",
|
|
"pre",
|
|
"code",
|
|
"a",
|
|
"img",
|
|
"table",
|
|
"thead",
|
|
"tbody",
|
|
"tr",
|
|
"th",
|
|
"td",
|
|
],
|
|
link: { rel: "noopener noreferrer nofollow", target: "_blank" },
|
|
} as const;
|
|
|
|
/** Validate decoded Markdown destinations; never resolve against the reader's page or repository. */
|
|
export function pluginOverviewUrl(value: string | undefined): string | undefined {
|
|
// URL parsers discard controls and normalize backslashes; reject those ambiguous spellings.
|
|
// eslint-disable-next-line no-control-regex
|
|
if (!value || !/^https:\/\/[^/?#]/i.test(value) || /[\u0000-\u0020\u007f\\]/.test(value))
|
|
return undefined;
|
|
try {
|
|
const url = new URL(value);
|
|
if (url.protocol !== "https:" || !url.hostname || url.username || url.password)
|
|
return undefined;
|
|
return value;
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}
|