src / snippets.ts
/**
* Pure builders for reusable OneNote XML snippets (hyperlinks, To Do tags).
* These produce fragments intended to be injected by other commands
* (append_to_page with content_format "html", update_page_xml, or the outline
* insert commands).
*/
import { cdata, escapeAttr, escapeText, oneT } from "./htmlToOneNote";
export interface TextFormatting {
bold?: boolean;
italic?: boolean;
underline?: boolean;
strikethrough?: boolean;
}
/** Build a `style="..."` value for the requested inline formatting, or "" if none. */
function formattingStyle(fmt: TextFormatting): string {
const parts: string[] = [];
if (fmt.bold) parts.push("font-weight:bold");
if (fmt.italic) parts.push("font-style:italic");
const decoration: string[] = [];
if (fmt.underline) decoration.push("underline");
if (fmt.strikethrough) decoration.push("line-through");
if (decoration.length) parts.push(`text-decoration:${decoration.join(" ")}`);
return parts.join(";");
}
/** Wrap escaped text in a formatting span if any formatting is requested. */
function formatText(text: string, fmt: TextFormatting): string {
const escaped = escapeText(text);
const style = formattingStyle(fmt);
return style ? `<span style="${style}">${escaped}</span>` : escaped;
}
export interface HyperlinkSnippet {
hyperlink_url: string;
inline_html: string;
one_t_xml: string;
one_oe_xml: string;
}
/**
* Build a hyperlink snippet for the given resolved OneNote URL and link text.
* - inline_html: an <a> fragment for content_format "html" insertion.
* - one_t_xml / one_oe_xml: OneNote XML for raw insertion into a page/table/OE.
*/
export function buildHyperlinkSnippet(url: string, text: string, fmt: TextFormatting = {}): HyperlinkSnippet {
const label = formatText(text, fmt);
const inline = `<a href="${escapeAttr(url)}">${label}</a>`;
return {
hyperlink_url: url,
inline_html: inline,
one_t_xml: oneT(inline),
one_oe_xml: `<one:OE>${oneT(inline)}</one:OE>`,
};
}
/** Build an array of hyperlink snippets for multiple URLs and texts. */
export function buildHyperlinkSnippets(items: { url: string; text: string; fmt?: TextFormatting }[]): HyperlinkSnippet[] {
return items.map((it) => buildHyperlinkSnippet(it.url, it.text, it.fmt ?? {}));
}
export interface TodoTagSnippet {
tag_index: number;
tag_def_xml: string;
tag_xml: string;
one_oe_xml?: string;
note: string;
}
/**
* Build the XML for OneNote's "To Do" tag (a checkbox).
* - tag_def_xml: the page-level <one:TagDef> (must exist on the page once, with
* this index) — inject it via update_page_xml if the page has none.
* - tag_xml: the <one:Tag> to place as the first child of a <one:OE>.
* - one_oe_xml: a ready <one:OE> combining the tag with the given text.
*/
export function buildTodoTagSnippet(opts: { text?: string; completed?: boolean; tagIndex?: number } = {}): TodoTagSnippet {
const index = opts.tagIndex ?? 0;
const completed = opts.completed ? "true" : "false";
const tagDef = `<one:TagDef index="${index}" type="0" symbol="3" fontColor="automatic" highlightColor="none" name="To Do"/>`;
const tag = `<one:Tag index="${index}" completed="${completed}" disabled="false"/>`;
const snippet: TodoTagSnippet = {
tag_index: index,
tag_def_xml: tagDef,
tag_xml: tag,
note:
"Place tag_def_xml once on the page (as a child of one:Page, before the outlines) if the page has no " +
"matching To Do TagDef; then use tag_xml as the first child of a one:OE, before its one:T.",
};
if (opts.text !== undefined && opts.text !== null) {
snippet.one_oe_xml = `<one:OE>${tag}${oneT(escapeText(opts.text))}</one:OE>`;
}
return snippet;
}