diff --git a/ts/input/tex/autoload/AutoloadConfiguration.ts b/ts/input/tex/autoload/AutoloadConfiguration.ts index aeb7888c1..6d24ac40b 100644 --- a/ts/input/tex/autoload/AutoloadConfiguration.ts +++ b/ts/input/tex/autoload/AutoloadConfiguration.ts @@ -154,7 +154,7 @@ export const AutoloadConfiguration = Configuration.create( color: ['color', 'definecolor', 'textcolor', 'colorbox', 'fcolorbox'], enclose: ['enclose'], extpfeil: ['xtwoheadrightarrow', 'xtwoheadleftarrow', 'xmapsto', 'xlongequal', 'xtofrom', 'Newextarrow'], - html: ['href', 'class', 'style', 'cssId'], + html: ['data', 'href', 'class', 'style', 'cssId'], mhchem: ['ce', 'pu'], newcommand: ['newcommand', 'renewcommand', 'newenvironment', 'renewenvironment', 'def', 'let'], unicode: ['unicode'], diff --git a/ts/input/tex/html/HtmlConfiguration.ts b/ts/input/tex/html/HtmlConfiguration.ts index 15340802c..5e1bbcd6e 100644 --- a/ts/input/tex/html/HtmlConfiguration.ts +++ b/ts/input/tex/html/HtmlConfiguration.ts @@ -28,6 +28,7 @@ import HtmlMethods from './HtmlMethods.js'; new CommandMap('html_macros', { + data: 'Data', href: 'Href', 'class': 'Class', style: 'Style', diff --git a/ts/input/tex/html/HtmlMethods.ts b/ts/input/tex/html/HtmlMethods.ts index 859294b05..69d14e461 100644 --- a/ts/input/tex/html/HtmlMethods.ts +++ b/ts/input/tex/html/HtmlMethods.ts @@ -26,12 +26,39 @@ import TexParser from '../TexParser.js'; import {ParseMethod} from '../Types.js'; import NodeUtil from '../NodeUtil.js'; +import ParseUtil from "../ParseUtil.js"; import {MmlNode} from '../../../core/MmlTree/MmlNode.js'; // Namespace let HtmlMethods: Record = {}; +/** + * Implements \data{dataset}{content} + * @param {TexParser} parser The calling parser. + * @param {string} name The macro name. + */ +HtmlMethods.Data = (parser: TexParser, name: string) => { + const dataset = parser.GetArgument(name); + const arg = GetArgumentMML(parser, name); + const data = ParseUtil.keyvalOptions(dataset); + for (const key in data) { + // remove illegal attribute names + if (!isLegalAttributeName(key)) { + continue; + } + NodeUtil.setAttribute(arg, `data-${key}`, data[key]); + } + parser.Push(arg); +}; + +/** + * Whether the string is a valid HTML attribute name according to {@link https://html.spec.whatwg.org/multipage/syntax.html#attributes-2}. + * @param {string} name String to validate. + */ +function isLegalAttributeName(name: string): boolean { + return Boolean(name.match(/^([^\x00-\x1f\x7f-\x9f "'>\/=]+)$/)); +} /** * Implements \href{url}{math} diff --git a/ts/input/tex/textmacros/TextMacrosMappings.ts b/ts/input/tex/textmacros/TextMacrosMappings.ts index 1f0fc8623..9f4ca2cf2 100644 --- a/ts/input/tex/textmacros/TextMacrosMappings.ts +++ b/ts/input/tex/textmacros/TextMacrosMappings.ts @@ -140,6 +140,7 @@ new CommandMap('text-macros', { href: 'CheckAutoload', style: 'CheckAutoload', class: 'CheckAutoload', + data: 'CheckAutoload', cssId: 'CheckAutoload', unicode: 'CheckAutoload',