Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 18 additions & 44 deletions javascript/packages/formatter/src/format-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const FORMATTABLE_ATTRIBUTES: Record<string, string[]> = {

export const INLINE_ELEMENTS = new Set([
'a', 'abbr', 'acronym', 'b', 'bdo', 'big', 'br', 'cite', 'code',
'dfn', 'em', 'i', 'img', 'kbd', 'label', 'map', 'object', 'q',
'dfn', 'em', 'hr', 'i', 'img', 'kbd', 'label', 'map', 'object', 'q',
'samp', 'small', 'span', 'strong', 'sub', 'sup',
'tt', 'var', 'del', 'ins', 'mark', 's', 'u', 'time', 'wbr'
])
Expand Down Expand Up @@ -139,15 +139,6 @@ export function filterSignificantChildren(body: Node[]): Node[] {
})
}

/**
* Filter out empty text nodes and whitespace nodes
*/
export function filterEmptyNodes(nodes: Node[]): Node[] {
return nodes.filter(child =>
!isNode(child, WhitespaceNode) && !(isNode(child, HTMLTextNode) && child.content.trim() === "")
)
}

/**
* Smart filter that preserves exactly ONE whitespace before herb:disable comments
*/
Expand Down Expand Up @@ -220,6 +211,7 @@ export function needsSpaceBetween(currentLine: string, word: string): boolean {
if (isClosingPunctuation(word)) return false
if (lineEndsWithOpeningPunctuation(currentLine)) return false
if (currentLine.endsWith(' ')) return false
if (word.startsWith(' ')) return false
if (endsWithERBTag(currentLine) && startsWithERBTag(word)) return false

return true
Expand Down Expand Up @@ -335,12 +327,8 @@ export function hasMultilineTextContent(children: Node[]): boolean {
return child.content.includes('\n')
}

if (isNode(child, HTMLElementNode)) {
const nestedChildren = filterEmptyNodes(child.body)

if (hasMultilineTextContent(nestedChildren)) {
return true
}
if (isNode(child, HTMLElementNode) && hasMultilineTextContent(child.body)) {
return true
}
}

Expand All @@ -357,9 +345,7 @@ export function areAllNestedElementsInline(children: Node[]): boolean {
return false
}

const nestedChildren = filterEmptyNodes(child.body)

if (!areAllNestedElementsInline(nestedChildren)) {
if (!areAllNestedElementsInline(child.body)) {
return false
}
} else if (isAnyOf(child, HTMLDoctypeNode, HTMLCommentNode, isERBControlFlowNode)) {
Expand Down Expand Up @@ -451,16 +437,6 @@ export function countAdjacentInlineElements(children: Node[]): number {
return count
}

/**
* Determine if we should wrap to the next line
*/
export function shouldWrapToNextLine(testLine: string, currentLine: string, word: string, wrapWidth: number): boolean {
if (!currentLine) return false
if (isClosingPunctuation(word)) return false

return testLine.length >= wrapWidth
}

/**
* Check if a node represents a block-level element
*/
Expand All @@ -479,27 +455,25 @@ export function isBlockLevelNode(node: Node): boolean {
}

/**
* Normalize text by replacing multiple spaces with single space and trim
* Then split into words
* Check if an element is a line-breaking element (br or hr)
*/
export function normalizeAndSplitWords(text: string): string[] {
const normalized = text.replace(/\s+/g, ' ')
return normalized.trim().split(' ')
}
export function isLineBreakingElement(node: Node): boolean {
if (!isNode(node, HTMLElementNode)) {
return false
}

/**
* Check if text starts with an alphanumeric character (not punctuation)
*/
export function startsWithAlphanumeric(text: string): boolean {
const trimmed = text.trim()
return /^[a-zA-Z0-9]/.test(trimmed)
const tagName = getTagName(node)

return tagName === 'br' || tagName === 'hr'
}

/**
* Check if text ends with an alphanumeric character (not punctuation)
* Normalize text by replacing multiple spaces with single space and trim
* Then split into words
*/
export function endsWithAlphanumeric(text: string): boolean {
return /[a-zA-Z0-9]$/.test(text)
export function normalizeAndSplitWords(text: string): string[] {
const normalized = text.replace(/\s+/g, ' ')
return normalized.trim().split(' ')
}

/**
Expand Down
Loading
Loading