Skip to content

Commit

Permalink
Merge pull request #10 from nickpharrison/protection_string
Browse files Browse the repository at this point in the history
Adding protection string options for Issue #9
  • Loading branch information
j4w8n authored Jan 6, 2025
2 parents b23445c + acc1efd commit 150dda3
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 21 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "htmlfy",
"version": "0.5.0",
"version": "0.5.1",
"description": "HTML formatter yo!. Prettify, minify, and more!",
"scripts": {
"check": "tsc",
Expand Down
3 changes: 2 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export const CONFIG = {
ignore: [],
strict: false,
tab_size: 2,
trim: []
trim: [],
ignore_with: '_!i-£___£%_',
}
6 changes: 4 additions & 2 deletions src/prettify.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,19 @@ export const prettify = (html, config) => {
const ignore = validated_config.ignore.length > 0
trim = validated_config.trim

const ignore_with = validated_config.ignore_with;

/* Protect ignored elements. */
if (ignore) {
html = ignoreElement(html, validated_config.ignore)
html = ignoreElement(html, validated_config.ignore, 'protect', ignore_with)
}

html = preprocess(html)
html = process(html, validated_config.tab_size)

/* Unprotect ignored elements. */
if (ignore) {
html = ignoreElement(html, validated_config.ignore, 'unprotect')
html = ignoreElement(html, validated_config.ignore, 'unprotect', ignore_with)
}

return html
Expand Down
1 change: 1 addition & 0 deletions src/types/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export interface DefaultConfig {
strict: boolean;
tab_size: number;
trim: string[];
ignore_with: string
}

type RecursiveRequired<T> = {
Expand Down
40 changes: 23 additions & 17 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,14 @@ export const mergeConfig = (dconfig, config) => {
*
* @param {string} html
* @param {string[]} ignore
* @param {string} [mode]
* @param {'protect'|'unprotect'} mode
* @param {string} ignore_with
* @returns {string}
*/
export const ignoreElement = (html, ignore, mode = 'protect') => {
export const ignoreElement = (html, ignore, mode, ignore_with) => {
for (let e = 0; e < ignore.length; e++) {
const regex = new RegExp(`<${ignore[e]}[^>]*>((.|\n)*?)<\/${ignore[e]}>`, "g")
html = html.replace(regex, mode === 'protect' ? protectElement : unprotectElement)
html = html.replace(regex, mode === 'protect' ? (match, capture) => protectElement(match, capture, ignore_with) : (match, capture) => unprotectElement(match, capture, ignore_with))
}

return html
Expand All @@ -81,16 +82,17 @@ export const ignoreElement = (html, ignore, mode = 'protect') => {
*
* @param {string} match
* @param {any} capture
* @param {string} protectionString
* @returns
*/
const protectElement = (match, capture) => {
const protectElement = (match, capture, protectionString) => {
return match.replace(capture, (match) => {
return match
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\n/g, '&#10;')
.replace(/\r/g, '&#13;')
.replace(/\s/g, '&nbsp;')
.replace(/</g, '-' + protectionString + 'lt-')
.replace(/>/g, '-' + protectionString + 'gt-')
.replace(/\n/g, '-' + protectionString + 'nl-')
.replace(/\r/g, '-' + protectionString + 'cr-')
.replace(/\s/g, '-' + protectionString + 'ws-')
})
}

Expand Down Expand Up @@ -120,16 +122,17 @@ export const trimify = (html, trim) => {
*
* @param {string} match
* @param {any} capture
* @param {string} protectionString
* @returns
*/
const unprotectElement = (match, capture) => {
const unprotectElement = (match, capture, protectionString) => {
return match.replace(capture, (match) => {
return match
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&#10;/g, '\n')
.replace(/&#13;/g, '\r')
.replace(/&nbsp;/g, ' ')
.replace(new RegExp('-' + protectionString + 'lt-', "g"), '<')
.replace(new RegExp('-' + protectionString + 'gt-', "g"), '>')
.replace(new RegExp('-' + protectionString + 'nl-', "g"), '\n')
.replace(new RegExp('-' + protectionString + 'cr-', "g"), '\r')
.replace(new RegExp('-' + protectionString + 'ws-', "g"), ' ')
})
}

Expand All @@ -146,7 +149,8 @@ export const validateConfig = (config) => {
Object.hasOwn(config, 'tab_size') ||
Object.hasOwn(config, 'strict') ||
Object.hasOwn(config, 'ignore') ||
Object.hasOwn(config, 'trim'))
Object.hasOwn(config, 'trim') ||
Object.hasOwn(config, 'ignore_with'))
if (config_empty) return CONFIG

let tab_size = config.tab_size
Expand All @@ -167,9 +171,11 @@ export const validateConfig = (config) => {
}

if (Object.hasOwn(config, 'strict') && typeof config.strict !== 'boolean')
throw new Error('Strict config must be a boolean.')
throw new Error(`Strict config must be a boolean, not ${typeof config.strict}.`)
if (Object.hasOwn(config, 'ignore') && (!Array.isArray(config.ignore) || !config.ignore?.every((e) => typeof e === 'string')))
throw new Error('Ignore config must be an array of strings.')
if (Object.hasOwn(config, 'ignore_with') && typeof config.ignore_with !== 'string')
throw new Error(`Ignore_with config must be a string, not ${typeof config.ignore_with}.`)
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.')

Expand Down
22 changes: 22 additions & 0 deletions tests/all.spec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { closify } from '../src/closify.js'
import { CONFIG } from '../src/constants.js'
import { entify } from '../src/entify.js'
import { minify } from '../src/minify.js'
import { prettify } from '../src/prettify.js'
import { trimify } from '../src/utils.js'
import { expect, test } from 'vitest'


const ugly_html = `<form id="3" > <!--
This is a comment. --><!-- This is a second comment. --><label for="email-0">
Expand Down Expand Up @@ -57,6 +59,10 @@ const config_html = `<form id="3">
<!-- This is a comment. -->
<!-- This is a second comment. --><div><br /><input /><br /><input /><div></div></div></form>`

const config_html_with_ignore_string = `<form id="3">
<!-- This is a comment. -->
<!-- This is a second comment. --><div><br /><input /><p>This contains &lt;angled&gt; brackets -${CONFIG.ignore_with}gt- and an unfortunate combination of characters</p><input /><div></div></div></form>`

const script_html = `<script>
document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1"></' + 'script>')
</script>
Expand Down Expand Up @@ -210,6 +216,22 @@ test('Tab size config', () => {
)
})

test('Default ignore_with in HTML', () => {
expect(prettify(config_html_with_ignore_string, { ignore: ['p'], ignore_with: '!!-H--_-98'})).toBe(
`<form id="3">
<!-- This is a comment. -->
<!-- This is a second comment. -->
<div>
<br />
<input />
<p>This contains &lt;angled&gt; brackets -_!i-£___£%_gt- and an unfortunate combination of characters</p>
<input />
<div></div>
</div>
</form>`
)
})

test('Catches invalid ignore config', async () => {
await expect(testConfig({ ignore: [ 'script', 1 ]})).rejects.toThrow('Ignore config must be an array of strings.')
})
Expand Down
1 change: 1 addition & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ declare module 'htmlfy' {
strict?: boolean;
tab_size?: number;
trim?: string[];
ignore_with?: string;
}

export type Config = Required<UserConfig>
Expand Down

0 comments on commit 150dda3

Please sign in to comment.