htmlfy
Version:
html formatter yo! Prettify or minify html.
88 lines (71 loc) • 2.86 kB
JavaScript
import { dentify, entify } from "./entify.js"
import { extractIgnoredBlocks, isHtml, reinsertIgnoredBlocks, validateConfig } from "./utils.js"
import { getState } from "./state.js"
/**
* @type {Map<any,any>}
*/
let ignore_map
/**
* Creates a single-line HTML string
* by removing line returns, tabs, and relevant spaces.
*
* @param {string} html The HTML string to minify.
* @param {import('htmlfy').UserConfig} [config] A user configuration object.
* @returns {string} A minified HTML string.
*/
export const minify = (html, config) => {
let reinsert_ignored = false
const { checked_html, ignored } = getState()
if (!checked_html && !isHtml(html)) return html
const validated_config = config ? validateConfig(config) : (getState()).config
const ignore = validated_config.ignore.length > 0
/* Extract ignored elements. Skipped if prettify has already ignored blocks. */
if (!ignored && ignore) {
const { html_with_markers, extracted_map } = extractIgnoredBlocks(html)
html = html_with_markers
ignore_map = extracted_map
reinsert_ignored = true
}
/**
* Ensure textarea content is protected
* before general minification.
*/
html = entify(html, true)
/* All other minification. */
// Remove ALL newlines and tabs explicitly.
html = html.replace(/\n|\t/g, '')
// Remove whitespace ONLY between tags.
html = html.replace(/>\s+</g, "><")
// Collapse any remaining multiple spaces to single spaces.
html = html.replace(/ {2,}/g, ' ')
// Remove specific single spaces between tags and whitespace within tags.
html = html.replace(/ >/g, ">") // <tag > -> <tag>
html = html.replace(/ </g, "<") // leading space before tag
html = html.replace(/> /g, ">") // trailing space after tag
html = html.replace(/< /g, "<") // < tag> -> <tag>
html = html.replace(/<\s+\//g, '</') // < /tag> -> </tag>
html = html.replace(/<\/\s+/g, '</') // </ tag> -> </tag>
// Trim spaces around equals signs in attributes (run before value trim)
// This handles `attr = "value"` -> `attr="value"`
html = html.replace(/ = /g, "=")
// Consider safer alternatives if needed (e.g., / = "/g, '="')
// Trim whitespace inside attribute values
html = html.replace(
/([a-zA-Z0-9_-]+)=(['"])(.*?)\2/g,
(match, attr_name, quote, value) => {
// value.trim() handles both leading/trailing spaces
// and cases where the value is only whitespace (becomes empty string)
const trimmed_value = value.trim()
return `${attr_name}=${quote}${trimmed_value}${quote}`
}
)
// Final trim for the whole string
html = html.trim()
/* Remove protective entities. */
html = dentify(html)
/* Re-insert ignored elements. Skipped unless minify did the ignore. */
if (reinsert_ignored) {
html = reinsertIgnoredBlocks(html, ignore_map)
}
return html
}