import { StackElementMetadata, INITIAL, Registry as Registry$1 } from './textmate.mjs'; import { FontStyle } from './types.mjs'; /** * List of HTML void tag names. * * @type {Array} */ const htmlVoidElements = [ 'area', 'base', 'basefont', 'bgsound', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'image', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr' ]; /** * @typedef {import('./info.js').Info} Info * @typedef {Record} Properties * @typedef {Record} Normal */ class Schema { /** * @constructor * @param {Properties} property * @param {Normal} normal * @param {string} [space] */ constructor(property, normal, space) { this.property = property; this.normal = normal; if (space) { this.space = space; } } } /** @type {Properties} */ Schema.prototype.property = {}; /** @type {Normal} */ Schema.prototype.normal = {}; /** @type {string|null} */ Schema.prototype.space = null; /** * @typedef {import('./schema.js').Properties} Properties * @typedef {import('./schema.js').Normal} Normal */ /** * @param {Schema[]} definitions * @param {string} [space] * @returns {Schema} */ function merge(definitions, space) { /** @type {Properties} */ const property = {}; /** @type {Normal} */ const normal = {}; let index = -1; while (++index < definitions.length) { Object.assign(property, definitions[index].property); Object.assign(normal, definitions[index].normal); } return new Schema(property, normal, space) } /** * @param {string} value * @returns {string} */ function normalize(value) { return value.toLowerCase() } class Info { /** * @constructor * @param {string} property * @param {string} attribute */ constructor(property, attribute) { /** @type {string} */ this.property = property; /** @type {string} */ this.attribute = attribute; } } /** @type {string|null} */ Info.prototype.space = null; Info.prototype.boolean = false; Info.prototype.booleanish = false; Info.prototype.overloadedBoolean = false; Info.prototype.number = false; Info.prototype.commaSeparated = false; Info.prototype.spaceSeparated = false; Info.prototype.commaOrSpaceSeparated = false; Info.prototype.mustUseProperty = false; Info.prototype.defined = false; let powers = 0; const boolean = increment(); const booleanish = increment(); const overloadedBoolean = increment(); const number = increment(); const spaceSeparated = increment(); const commaSeparated = increment(); const commaOrSpaceSeparated = increment(); function increment() { return 2 ** ++powers } var types = /*#__PURE__*/Object.freeze({ __proto__: null, boolean: boolean, booleanish: booleanish, commaOrSpaceSeparated: commaOrSpaceSeparated, commaSeparated: commaSeparated, number: number, overloadedBoolean: overloadedBoolean, spaceSeparated: spaceSeparated }); /** @type {Array} */ // @ts-expect-error: hush. const checks = Object.keys(types); class DefinedInfo extends Info { /** * @constructor * @param {string} property * @param {string} attribute * @param {number|null} [mask] * @param {string} [space] */ constructor(property, attribute, mask, space) { let index = -1; super(property, attribute); mark(this, 'space', space); if (typeof mask === 'number') { while (++index < checks.length) { const check = checks[index]; mark(this, checks[index], (mask & types[check]) === types[check]); } } } } DefinedInfo.prototype.defined = true; /** * @param {DefinedInfo} values * @param {string} key * @param {unknown} value */ function mark(values, key, value) { if (value) { // @ts-expect-error: assume `value` matches the expected value of `key`. values[key] = value; } } /** * @typedef {import('./schema.js').Properties} Properties * @typedef {import('./schema.js').Normal} Normal * * @typedef {Record} Attributes * * @typedef {Object} Definition * @property {Record} properties * @property {(attributes: Attributes, property: string) => string} transform * @property {string} [space] * @property {Attributes} [attributes] * @property {Array} [mustUseProperty] */ const own$3 = {}.hasOwnProperty; /** * @param {Definition} definition * @returns {Schema} */ function create(definition) { /** @type {Properties} */ const property = {}; /** @type {Normal} */ const normal = {}; /** @type {string} */ let prop; for (prop in definition.properties) { if (own$3.call(definition.properties, prop)) { const value = definition.properties[prop]; const info = new DefinedInfo( prop, definition.transform(definition.attributes || {}, prop), value, definition.space ); if ( definition.mustUseProperty && definition.mustUseProperty.includes(prop) ) { info.mustUseProperty = true; } property[prop] = info; normal[normalize(prop)] = prop; normal[normalize(info.attribute)] = prop; } } return new Schema(property, normal, definition.space) } const xlink = create({ space: 'xlink', transform(_, prop) { return 'xlink:' + prop.slice(5).toLowerCase() }, properties: { xLinkActuate: null, xLinkArcRole: null, xLinkHref: null, xLinkRole: null, xLinkShow: null, xLinkTitle: null, xLinkType: null } }); const xml = create({ space: 'xml', transform(_, prop) { return 'xml:' + prop.slice(3).toLowerCase() }, properties: {xmlLang: null, xmlBase: null, xmlSpace: null} }); /** * @param {Record} attributes * @param {string} attribute * @returns {string} */ function caseSensitiveTransform(attributes, attribute) { return attribute in attributes ? attributes[attribute] : attribute } /** * @param {Record} attributes * @param {string} property * @returns {string} */ function caseInsensitiveTransform(attributes, property) { return caseSensitiveTransform(attributes, property.toLowerCase()) } const xmlns = create({ space: 'xmlns', attributes: {xmlnsxlink: 'xmlns:xlink'}, transform: caseInsensitiveTransform, properties: {xmlns: null, xmlnsXLink: null} }); const aria = create({ transform(_, prop) { return prop === 'role' ? prop : 'aria-' + prop.slice(4).toLowerCase() }, properties: { ariaActiveDescendant: null, ariaAtomic: booleanish, ariaAutoComplete: null, ariaBusy: booleanish, ariaChecked: booleanish, ariaColCount: number, ariaColIndex: number, ariaColSpan: number, ariaControls: spaceSeparated, ariaCurrent: null, ariaDescribedBy: spaceSeparated, ariaDetails: null, ariaDisabled: booleanish, ariaDropEffect: spaceSeparated, ariaErrorMessage: null, ariaExpanded: booleanish, ariaFlowTo: spaceSeparated, ariaGrabbed: booleanish, ariaHasPopup: null, ariaHidden: booleanish, ariaInvalid: null, ariaKeyShortcuts: null, ariaLabel: null, ariaLabelledBy: spaceSeparated, ariaLevel: number, ariaLive: null, ariaModal: booleanish, ariaMultiLine: booleanish, ariaMultiSelectable: booleanish, ariaOrientation: null, ariaOwns: spaceSeparated, ariaPlaceholder: null, ariaPosInSet: number, ariaPressed: booleanish, ariaReadOnly: booleanish, ariaRelevant: null, ariaRequired: booleanish, ariaRoleDescription: spaceSeparated, ariaRowCount: number, ariaRowIndex: number, ariaRowSpan: number, ariaSelected: booleanish, ariaSetSize: number, ariaSort: null, ariaValueMax: number, ariaValueMin: number, ariaValueNow: number, ariaValueText: null, role: null } }); const html$3 = create({ space: 'html', attributes: { acceptcharset: 'accept-charset', classname: 'class', htmlfor: 'for', httpequiv: 'http-equiv' }, transform: caseInsensitiveTransform, mustUseProperty: ['checked', 'multiple', 'muted', 'selected'], properties: { // Standard Properties. abbr: null, accept: commaSeparated, acceptCharset: spaceSeparated, accessKey: spaceSeparated, action: null, allow: null, allowFullScreen: boolean, allowPaymentRequest: boolean, allowUserMedia: boolean, alt: null, as: null, async: boolean, autoCapitalize: null, autoComplete: spaceSeparated, autoFocus: boolean, autoPlay: boolean, capture: boolean, charSet: null, checked: boolean, cite: null, className: spaceSeparated, cols: number, colSpan: null, content: null, contentEditable: booleanish, controls: boolean, controlsList: spaceSeparated, coords: number | commaSeparated, crossOrigin: null, data: null, dateTime: null, decoding: null, default: boolean, defer: boolean, dir: null, dirName: null, disabled: boolean, download: overloadedBoolean, draggable: booleanish, encType: null, enterKeyHint: null, form: null, formAction: null, formEncType: null, formMethod: null, formNoValidate: boolean, formTarget: null, headers: spaceSeparated, height: number, hidden: boolean, high: number, href: null, hrefLang: null, htmlFor: spaceSeparated, httpEquiv: spaceSeparated, id: null, imageSizes: null, imageSrcSet: null, inputMode: null, integrity: null, is: null, isMap: boolean, itemId: null, itemProp: spaceSeparated, itemRef: spaceSeparated, itemScope: boolean, itemType: spaceSeparated, kind: null, label: null, lang: null, language: null, list: null, loading: null, loop: boolean, low: number, manifest: null, max: null, maxLength: number, media: null, method: null, min: null, minLength: number, multiple: boolean, muted: boolean, name: null, nonce: null, noModule: boolean, noValidate: boolean, onAbort: null, onAfterPrint: null, onAuxClick: null, onBeforeMatch: null, onBeforePrint: null, onBeforeUnload: null, onBlur: null, onCancel: null, onCanPlay: null, onCanPlayThrough: null, onChange: null, onClick: null, onClose: null, onContextLost: null, onContextMenu: null, onContextRestored: null, onCopy: null, onCueChange: null, onCut: null, onDblClick: null, onDrag: null, onDragEnd: null, onDragEnter: null, onDragExit: null, onDragLeave: null, onDragOver: null, onDragStart: null, onDrop: null, onDurationChange: null, onEmptied: null, onEnded: null, onError: null, onFocus: null, onFormData: null, onHashChange: null, onInput: null, onInvalid: null, onKeyDown: null, onKeyPress: null, onKeyUp: null, onLanguageChange: null, onLoad: null, onLoadedData: null, onLoadedMetadata: null, onLoadEnd: null, onLoadStart: null, onMessage: null, onMessageError: null, onMouseDown: null, onMouseEnter: null, onMouseLeave: null, onMouseMove: null, onMouseOut: null, onMouseOver: null, onMouseUp: null, onOffline: null, onOnline: null, onPageHide: null, onPageShow: null, onPaste: null, onPause: null, onPlay: null, onPlaying: null, onPopState: null, onProgress: null, onRateChange: null, onRejectionHandled: null, onReset: null, onResize: null, onScroll: null, onScrollEnd: null, onSecurityPolicyViolation: null, onSeeked: null, onSeeking: null, onSelect: null, onSlotChange: null, onStalled: null, onStorage: null, onSubmit: null, onSuspend: null, onTimeUpdate: null, onToggle: null, onUnhandledRejection: null, onUnload: null, onVolumeChange: null, onWaiting: null, onWheel: null, open: boolean, optimum: number, pattern: null, ping: spaceSeparated, placeholder: null, playsInline: boolean, poster: null, preload: null, readOnly: boolean, referrerPolicy: null, rel: spaceSeparated, required: boolean, reversed: boolean, rows: number, rowSpan: number, sandbox: spaceSeparated, scope: null, scoped: boolean, seamless: boolean, selected: boolean, shape: null, size: number, sizes: null, slot: null, span: number, spellCheck: booleanish, src: null, srcDoc: null, srcLang: null, srcSet: null, start: number, step: null, style: null, tabIndex: number, target: null, title: null, translate: null, type: null, typeMustMatch: boolean, useMap: null, value: booleanish, width: number, wrap: null, // Legacy. // See: https://html.spec.whatwg.org/#other-elements,-attributes-and-apis align: null, // Several. Use CSS `text-align` instead, aLink: null, // ``. Use CSS `a:active {color}` instead archive: spaceSeparated, // ``. List of URIs to archives axis: null, // `` and ``. Use `scope` on `` background: null, // ``. Use CSS `background-image` instead bgColor: null, // `` and table elements. Use CSS `background-color` instead border: number, // ``. Use CSS `border-width` instead, borderColor: null, // `
`. Use CSS `border-color` instead, bottomMargin: number, // `` cellPadding: null, // `
` cellSpacing: null, // `
` char: null, // Several table elements. When `align=char`, sets the character to align on charOff: null, // Several table elements. When `char`, offsets the alignment classId: null, // `` clear: null, // `
`. Use CSS `clear` instead code: null, // `` codeBase: null, // `` codeType: null, // `` color: null, // `` and `
`. Use CSS instead compact: boolean, // Lists. Use CSS to reduce space between items instead declare: boolean, // `` event: null, // `