Comparing version 0.4.0 to 0.5.0
{ | ||
"name": "htmlfy", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "HTML formatter yo!. Prettify, minify, and more!", | ||
@@ -5,0 +5,0 @@ "exports": { |
@@ -19,3 +19,3 @@ # htmlfy | ||
### Prettify | ||
Turn single-line or ugly HTML into highly formatted HTML. This is a wrapper for all other functions, and then it adds indentation. | ||
Turn single-line or ugly HTML into highly formatted HTML. This is a wrapper for all other functions, except `trimify`, and then it adds indentation. | ||
@@ -93,2 +93,15 @@ ```js | ||
### Trimify | ||
Trim leading and trailing whitespace for whatever HTML element(s) you'd like. This is a standalone function, which is not run with `prettify` by default. | ||
```js | ||
import { trimify } from 'htmlfy' | ||
const html = `<div> | ||
Hello World | ||
</div>` | ||
console.log(trimify(html, [ 'div' ])) | ||
/* <div>Hello World</div> */ | ||
``` | ||
### Default Import | ||
@@ -182,1 +195,14 @@ If needed, you can use a default import for `htmlfy`. | ||
``` | ||
### Trim | ||
Trim leading and trailing whitespace from `textarea` elements, since all whitespace is preserved by default. | ||
```js | ||
import { prettify } from 'htmlfy' | ||
const html = '<textarea> Hello World </textarea>' | ||
console.log(prettify(html, { trim: [ 'textarea' ]})) | ||
/*<textarea>Hello World</textarea>*/ | ||
``` | ||
> For compatibility and possible future expansion, we require declaring an array with the value 'textarea', as opposed to using something like `{ trim: true }`. Passing in additional HTML element values has no effect, since we already trim whitespace for all other elements. |
@@ -5,5 +5,6 @@ /** | ||
export const CONFIG = { | ||
ignore: {}, | ||
ignore: [], | ||
strict: false, | ||
tab_size: 2 | ||
tab_size: 2, | ||
trim: [] | ||
} |
/** | ||
* Enforce entity characters for textarea content. | ||
* By default, this also does basic minification before setting entities. | ||
* For full minification, pass `minify_content` as `true`. | ||
* To also minifiy, pass `minify` as `true`. | ||
* | ||
@@ -14,14 +13,4 @@ * @param {string} html The HTML string to evaluate. | ||
export const entify = (html, minify = false) => { | ||
/* Trim any combination of leading line returns and/or spaces. */ | ||
html = html | ||
.replace(/(<textarea[^>]*>)\n+/g, '$1') | ||
.replace(/(<textarea[^>]*>)\n\s+/g, '$1') | ||
.replace(/(<textarea[^>]*>)\s+\n/g, '$1') | ||
/* Trim trailing spaces */ | ||
html = html.replace(/\s+<\/textarea>/g, '</textarea>') | ||
/** | ||
* Protect entities, inside the textarea content, | ||
* from general minification. | ||
* Use entities inside textarea content. | ||
*/ | ||
@@ -33,9 +22,7 @@ html = html.replace(/<textarea[^>]*>((.|\n)*?)<\/textarea>/g, (match, capture) => { | ||
.replace(/>/g, '>') | ||
.replace(/\//g, '/') | ||
.replace(/"/g, '"') | ||
.replace(/'/g, ''') | ||
.replace(/\n/g, ' ') | ||
.replace(/%/g, '%') | ||
.replace(/\{/g, '{') | ||
.replace(/\}/g, '}') | ||
.replace(/"/g, '"') | ||
.replace(/'/g, ''') | ||
.replace(/\n/g, ' ') | ||
.replace(/\r/g, ' ') | ||
.replace(/\s/g, ' ') | ||
}) | ||
@@ -42,0 +29,0 @@ }) |
@@ -5,1 +5,2 @@ export { closify } from '../closify.js' | ||
export { prettify } from '../prettify.js' | ||
export { trimify } from '../utils.js' |
import { closify } from './closify.js' | ||
import { minify } from './minify.js' | ||
import { ignoreElement, isHtml, validateConfig } from './utils.js' | ||
import { ignoreElement, isHtml, trimify, validateConfig } from './utils.js' | ||
import { CONFIG } from './constants.js' | ||
@@ -12,2 +12,7 @@ | ||
/** | ||
* @type {string[]} | ||
*/ | ||
let trim | ||
/** | ||
* @type {{ line: string[] }} | ||
@@ -51,2 +56,6 @@ */ | ||
html = closify(html, false) | ||
if (trim.length > 0) | ||
html = trimify(html, trim) | ||
html = minify(html, false) | ||
@@ -152,3 +161,4 @@ html = enqueue(html) | ||
const ignore = Object.keys(validated_config.ignore).length > 0 | ||
const ignore = validated_config.ignore.length > 0 | ||
trim = validated_config.trim | ||
@@ -155,0 +165,0 @@ /* Protect ignored elements. */ |
export interface DefaultConfig { | ||
ignore: Record<string, string>; | ||
ignore: string[]; | ||
strict: boolean; | ||
tab_size: number; | ||
trim: string[]; | ||
} | ||
@@ -6,0 +7,0 @@ |
@@ -24,13 +24,19 @@ import { CONFIG } from './constants.js' | ||
throw new Error("Both 'current' and 'updates' must be passed-in to merge()") | ||
if (typeof current !== 'object' || typeof updates !== 'object') | ||
throw new Error("Both 'current' and 'updates' must be passed-in as objects to merge()") | ||
let merged = { ...current } | ||
for (let key of Object.keys(updates)) { | ||
if (typeof updates[key] !== 'object') { | ||
merged[key] = updates[key] | ||
} else { | ||
/* key is an object, run mergeObjects again. */ | ||
merged[key] = mergeObjects(merged[key] || {}, updates[key]) | ||
/** | ||
* @type {any} | ||
*/ | ||
let merged | ||
if (Array.isArray(current)) { | ||
merged = structuredClone(current).concat(updates) | ||
} else if (typeof current === 'object') { | ||
merged = { ...current } | ||
for (let key of Object.keys(updates)) { | ||
if (typeof updates[key] !== 'object') { | ||
merged[key] = updates[key] | ||
} else { | ||
/* key is an object, run mergeObjects again. */ | ||
merged[key] = mergeObjects(merged[key] || {}, updates[key]) | ||
} | ||
} | ||
@@ -61,3 +67,3 @@ } | ||
* @param {string} html | ||
* @param {Record<string, string>} ignore | ||
* @param {string[]} ignore | ||
* @param {string} [mode] | ||
@@ -67,3 +73,3 @@ * @returns {string} | ||
export const ignoreElement = (html, ignore, mode = 'protect') => { | ||
for (let e = 0; e < Object.keys(ignore).length; e++) { | ||
for (let e = 0; e < ignore.length; e++) { | ||
const regex = new RegExp(`<${ignore[e]}[^>]*>((.|\n)*?)<\/${ignore[e]}>`, "g") | ||
@@ -88,9 +94,4 @@ html = html.replace(regex, mode === 'protect' ? protectElement : unprotectElement) | ||
.replace(/>/g, '>') | ||
.replace(/\//g, '/') | ||
.replace(/"/g, '"') | ||
.replace(/'/g, ''') | ||
.replace(/\n/g, ' ') | ||
.replace(/%/g, '%') | ||
.replace(/\{/g, '{') | ||
.replace(/\}/g, '}') | ||
.replace(/\n/g, ' ') | ||
.replace(/\r/g, ' ') | ||
.replace(/\s/g, ' ') | ||
@@ -101,2 +102,23 @@ }) | ||
/** | ||
* Trim leading and trailing whitespace characters. | ||
* | ||
* @param {string} html | ||
* @param {string[]} trim | ||
* @returns {string} | ||
*/ | ||
export const trimify = (html, trim) => { | ||
for (let e = 0; e < trim.length; e++) { | ||
/* Whitespace character must be escaped with '\' or RegExp() won't include it. */ | ||
const leading_whitespace = new RegExp(`(<${trim[e]}[^>]*>)\\s+`, "g") | ||
const trailing_whitespace = new RegExp(`\\s+(</${trim[e]}>)`, "g") | ||
html = html | ||
.replace(leading_whitespace, '$1') | ||
.replace(trailing_whitespace, '$1') | ||
} | ||
return html | ||
} | ||
/** | ||
* Unprotect an element by removing entities. | ||
@@ -113,9 +135,4 @@ * | ||
.replace(/>/g, '>') | ||
.replace(///g, '/') | ||
.replace(/"/g, '"') | ||
.replace(/'/g, "'") | ||
.replace(/ /g, '\n') | ||
.replace(/%/g, '%') | ||
.replace(/{/g, '{') | ||
.replace(/}/g, '}') | ||
.replace(/ /g, '\n') | ||
.replace(/ /g, '\r') | ||
.replace(/ /g, ' ') | ||
@@ -134,3 +151,7 @@ }) | ||
const config_empty = !(Object.hasOwn(config, 'tab_size') || Object.hasOwn(config, 'strict') || Object.hasOwn(config, 'ignore')) | ||
const config_empty = !( | ||
Object.hasOwn(config, 'tab_size') || | ||
Object.hasOwn(config, 'strict') || | ||
Object.hasOwn(config, 'ignore') || | ||
Object.hasOwn(config, 'trim')) | ||
if (config_empty) return CONFIG | ||
@@ -159,2 +180,4 @@ | ||
throw new Error('Ignore config must be an array of strings.') | ||
if (Object.hasOwn(config, 'trim') && (!Array.isArray(config.trim) || !config.trim?.every((e) => typeof e === 'string'))) | ||
throw new Error('Trim config must be an array of strings.') | ||
@@ -161,0 +184,0 @@ return mergeConfig(CONFIG, config) |
@@ -6,9 +6,6 @@ declare module 'htmlfy' { | ||
tab_size?: number; | ||
trim?: string[]; | ||
} | ||
export interface Config { | ||
ignore: Record<string, string>; | ||
strict: boolean; | ||
tab_size: number; | ||
} | ||
export type Config = Required<UserConfig> | ||
@@ -57,2 +54,11 @@ /** | ||
export function prettify(html: string, config?: UserConfig): string | ||
/** | ||
* Trim leading and trailing whitespace from the defined HTML elements. | ||
* | ||
* @param {string} html | ||
* @param {string[]} trim | ||
* @returns A trimmed string. | ||
*/ | ||
export function trimify(html: string, trim: string[]): string | ||
} |
23679
486
206