From adf0adde987a368298e135c23ce307efbc38d888 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 16 Aug 2023 15:18:47 -0300 Subject: html: move parseAttributes from replacer into html lib It also always returns an html.Attributes object, instead of a key/value mapping (which would be provided to html.attributes). --- src/util/html.js | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'src/util/html.js') diff --git a/src/util/html.js b/src/util/html.js index 19a7d126..712a0a68 100644 --- a/src/util/html.js +++ b/src/util/html.js @@ -424,6 +424,10 @@ export function attributes(attributes) { return new Attributes(attributes); } +export function parseAttributes(string) { + return Attributes.parse(string); +} + export class Attributes { #attributes = Object.create(null); @@ -496,6 +500,66 @@ export class Attributes { .replaceAll('"', '"') .replaceAll("'", '''); } + + static parse(string) { + const attributes = Object.create(null); + + const skipWhitespace = i => { + if (!/\s/.test(string[i])) { + return i; + } + + const match = string.slice(i).match(/[^\s]/); + if (match) { + return i + match.index; + } + + return string.length; + }; + + for (let i = 0; i < string.length; ) { + i = skipWhitespace(i); + const aStart = i; + const aEnd = i + string.slice(i).match(/[\s=]|$/).index; + const attribute = string.slice(aStart, aEnd); + i = skipWhitespace(aEnd); + if (string[i] === '=') { + i = skipWhitespace(i + 1); + let end, endOffset; + if (string[i] === '"' || string[i] === "'") { + end = string[i]; + endOffset = 1; + i++; + } else { + end = '\\s'; + endOffset = 0; + } + const vStart = i; + const vEnd = i + string.slice(i).match(new RegExp(`${end}|$`)).index; + const value = string.slice(vStart, vEnd); + i = vEnd + endOffset; + attributes[attribute] = value; + } else { + attributes[attribute] = attribute; + } + } + + return ( + Reflect.construct(this, [ + Object.fromEntries( + Object.entries(attributes) + .map(([key, val]) => [ + key, + (val === 'true' + ? true + : val === 'false' + ? false + : val === key + ? true + : val), + ])), + ])); + } } export function resolve(tagOrTemplate) { -- cgit 1.3.0-6-gf8a5