use non-validating HTML formatter
This commit is contained in:
parent
5eb23a4554
commit
1f472e5c2c
|
|
@ -14,7 +14,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"hono": "^4.10.4",
|
"hono": "^4.10.4",
|
||||||
"kleur": "^4.1.5",
|
"hype": "^0.0.3",
|
||||||
"prettier": "^3.7.3"
|
"kleur": "^4.1.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
141
src/html-formatter.js
Normal file
141
src/html-formatter.js
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
// HTML Formatter
|
||||||
|
// https://github.com/uznam8x/html-formatter
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
const single = [
|
||||||
|
'br', 'hr', 'img', 'input', 'meta', 'link',
|
||||||
|
'col', 'base', 'param', 'track', 'source', 'wbr',
|
||||||
|
'command', 'keygen', 'area', 'embed', 'menuitem'
|
||||||
|
];
|
||||||
|
|
||||||
|
const closing = function(el) {
|
||||||
|
el = el.replace(/<([a-zA-Z\-0-9]+)[^>]*>/g, function(match, capture) {
|
||||||
|
if (single.indexOf(capture) > -1) {
|
||||||
|
return (match.substring(0, match.length - 1) + ' />').replace(/\/\s\//g, '/');
|
||||||
|
}
|
||||||
|
return match.replace(/[\s]?\/>/g, '></' + capture + '>');
|
||||||
|
});
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
const entity = function(el) {
|
||||||
|
el = el.replace(/(<textarea[^>]*>)\n\s+/g, '$1');
|
||||||
|
el = el.replace(/\s+<\/textarea>/g, '</textarea>');
|
||||||
|
el = el.replace(/<textarea[^>]*>((.|\n)*?)<\/textarea>/g, function(match, capture) {
|
||||||
|
return match.replace(capture, function(match) {
|
||||||
|
return match
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/\//g, '/')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''')
|
||||||
|
.replace(/\n/g, ' ')
|
||||||
|
.replace(/%/g, '%')
|
||||||
|
.replace(/\{/g, '{')
|
||||||
|
.replace(/\}/g, '}')
|
||||||
|
.replace(/\s/g, ' ');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
const minify = function(el) {
|
||||||
|
return el
|
||||||
|
.replace(/\n|\t/g, '')
|
||||||
|
.replace(/[a-z]+="\s*"/ig, '')
|
||||||
|
.replace(/>\s+</g, '><')
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.replace(/\s>/g, '>')
|
||||||
|
.replace(/>\s/g, '>')
|
||||||
|
.replace(/\s</g, '<')
|
||||||
|
.replace(/class=["']\s/g, function(match) {
|
||||||
|
return match.replace(/\s/g, '');
|
||||||
|
})
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convert = {
|
||||||
|
comment: [],
|
||||||
|
line: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const comment = function (el) {
|
||||||
|
convert.comment = [];
|
||||||
|
|
||||||
|
el = el.replace(/(<!--(.|\n)*?-->)/g, function (match) {
|
||||||
|
convert.comment.push(match);
|
||||||
|
return '<!-- [#!# : ' + (convert.comment.length - 1) + ' : #!#] -->';
|
||||||
|
});
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
const line = function (el) {
|
||||||
|
convert.line = [];
|
||||||
|
let i = -1;
|
||||||
|
el = el.replace(/<[^>]*>/g, function (match) {
|
||||||
|
convert.line.push(match);
|
||||||
|
i++;
|
||||||
|
return '\n[#-# : ' + i + ' : ' + match + ' : #-#]\n';
|
||||||
|
});
|
||||||
|
el = el.replace(/\n\n/g, '\n');
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
const tidy = function (el) {
|
||||||
|
let tab = '';
|
||||||
|
convert.line.forEach(function (source, index) {
|
||||||
|
el = el.replace('[#-# : ' + index + ' : ' + source + ' : #-#]', function (match) {
|
||||||
|
const prevLine = '[#-# : ' + (index - 1) + ' : ' + convert.line[index - 1] + ' : #-#]';
|
||||||
|
tab += '\t';
|
||||||
|
let remove = 0;
|
||||||
|
if (index === 0) remove++;
|
||||||
|
if (match.indexOf('#-# : ' + (index) + ' : </') > -1) remove++;
|
||||||
|
if (prevLine.indexOf('<!doctype') > -1) remove++;
|
||||||
|
if (prevLine.indexOf('<!--') > -1) remove++;
|
||||||
|
if (prevLine.indexOf('/> : #-#') > -1) remove++;
|
||||||
|
if (prevLine.indexOf('#-# : ' + (index - 1) + ' : </') > -1) remove++;
|
||||||
|
if (match.indexOf('<!--') > -1) {
|
||||||
|
match = match.replace('<!-- [#!# :', '<!-- [#!# %' + (tab.length - remove) + '% :');
|
||||||
|
}
|
||||||
|
tab = tab.substring(0, tab.length - remove);
|
||||||
|
return tab + match.replace('[#-# : ' + index + ' : ', '').replace(' : #-#]', '');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
el = el.replace(/>[^<]*?[^><\/\s][^<]*?<\/|>\s+[^><\s]|<script[^>]*>\s+<\/script>|<(\w+)>\s+<\/(\w+)|<(\w+)[^>]*>\s<\/(\w+)>|<([\w\-]+)[^>]*[^\/]>\s+<\/([\w\-]+)>/g, function(match) {
|
||||||
|
return match.replace(/\n|\t/g, '');
|
||||||
|
})
|
||||||
|
|
||||||
|
const generateTab = function(cnt){
|
||||||
|
let t = '';
|
||||||
|
for (let c = 0; c < cnt; c++) {
|
||||||
|
t += '\t';
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
convert.comment.forEach(function (source, index) {
|
||||||
|
el = el.replace(new RegExp('<!--[^>]*' + index + ' : #!#] -->', 'g'), function (match) {
|
||||||
|
const cnt = /%(\d+)%/g.exec(match);
|
||||||
|
const t = generateTab(cnt[1]);
|
||||||
|
return source.replace(/\n/g, '\n'+t);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return el.substring(1, el.length - 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const render = function (el, opt) {
|
||||||
|
el = closing(el);
|
||||||
|
el = comment(el);
|
||||||
|
el = entity(el);
|
||||||
|
el = minify(el);
|
||||||
|
el = line(el);
|
||||||
|
el = tidy(el);
|
||||||
|
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Export for ES modules
|
||||||
|
export { closing, entity, minify, render };
|
||||||
|
export default render;
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import prettier from 'prettier'
|
import { render as formatHTML } from './html-formatter'
|
||||||
import { type Context, Hono, type Schema, type Env } from 'hono'
|
import { type Context, Hono, type Schema, type Env } from 'hono'
|
||||||
import { serveStatic } from 'hono/bun'
|
import { serveStatic } from 'hono/bun'
|
||||||
import color from 'kleur'
|
import color from 'kleur'
|
||||||
|
|
@ -78,7 +78,7 @@ export class Hype<
|
||||||
|
|
||||||
if (c.res.headers.get('content-type')?.includes('text/html')) {
|
if (c.res.headers.get('content-type')?.includes('text/html')) {
|
||||||
const html = await c.res.text()
|
const html = await c.res.text()
|
||||||
const formatted = await prettier.format(html, { parser: 'html' })
|
const formatted = formatHTML(html)
|
||||||
c.res = new Response(formatted, c.res)
|
c.res = new Response(formatted, c.res)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user