diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2024-03-26 09:34:22 -0300 |
---|---|---|
committer | (quasar) nebula <qznebula@protonmail.com> | 2024-03-26 09:37:11 -0300 |
commit | bf4c680ec16267e4757e773317cc56c5603bbb68 (patch) | |
tree | 2ff1cb6e83971f51c0a12758f97757b178d4e784 | |
parent | 9b1047826fae0f7f3d4f8cad814e4be1e280e46a (diff) |
html: html.smush(), Tag.smush()
-rw-r--r-- | src/util/html.js | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/util/html.js b/src/util/html.js index 944eab78..c7157a8b 100644 --- a/src/util/html.js +++ b/src/util/html.js @@ -619,6 +619,61 @@ export class Tag { return new Tag(null, null, content); } + smush() { + if (!this.contentOnly) { + return tags([this]); + } + + const joiner = this.#getContentJoiner(); + + const result = []; + + let workingText = ''; + + for (const item of this.content) { + const smushed = smush(item); + const smushedItems = smushed.content.slice(); + + if (empty(smushedItems)) { + continue; + } + + if (typeof smushedItems[0] === 'string') { + if (workingText) { + workingText += joiner; + } + + workingText += smushedItems.shift(); + } + + if (empty(smushedItems)) { + continue; + } + + if (workingText) { + result.push(workingText); + } + + if (typeof smushedItems.at(-1) === 'string') { + workingText = smushedItems.pop(); + } else { + workingText = ''; + } + + result.push(...smushedItems); + } + + if (workingText) { + result.push(workingText); + } + + const attributes = { + [joinChildren]: this.joinChildren, + }; + + return new Tag(null, attributes, result); + } + [inspect.custom](depth, opts) { const lines = []; @@ -1111,6 +1166,31 @@ export function resolve(tagOrTemplate, {normalize = null} = {}) { } } +export function smush(smushee) { + if ( + typeof smushee === 'string' || + typeof smushee === 'number' + ) { + return tags([smushee.toString()]); + } + + if (smushee instanceof Template) { + // Smushing is only really useful if the contents are resolved, because + // otherwise we can't actually inspect the boundaries. However, as usual + // for smushing, we don't care at all about the contents of tags (which + // aren't contentOnly) *within* the content we're smushing, so this won't + // for example smush a template nested within a *tag* within the contents + // of this template. + return smush(Template.resolve(smushee)); + } + + if (smushee instanceof Tag) { + return smushee.smush(); + } + + return smush(Tag.normalize(smushee)); +} + export function template(description) { return new Template(description); } |