Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Export stripWhitespace function for direct string minification #237

Merged
merged 2 commits into from
Aug 7, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Expand Up @@ -115,8 +115,12 @@ codeEditor.setContent(`

## Standalone minification

### Template literals

You can also do template literal minification separately. The `minify` function takes JavaScript source code as input and will minify template literals within it. It also takes the same options as `minifyTemplates` as a second argument.

Also note that this exports a `MagicString` instance, so you need to call [magicstring's `.toString()`](https://github.com/Rich-Harris/magic-string#stostring) on it.

```js
import { minify } from 'esbuild-minify-templates';

Expand All @@ -125,6 +129,18 @@ const result = minify('let a = `x y`;');
console.log(result.toString()); // 'let a = `x y`;'
```

### HTML code strings

In situations where you have HTML code as a plain string, this package also exports a `stripWhitespace` function for standalone use.

```js
import { stripWhitespace } from 'esbuild-minify-templates';

const result = stripWhitespace('x y');

console.log(result); // 'x y'
```

## Changelog

See [releases on GitHub](https://github.com/maxmilton/esbuild-minify-templates/releases).
Expand Down
42 changes: 25 additions & 17 deletions src/index.ts
Expand Up @@ -29,6 +29,26 @@ const decoder = new TextDecoder();
export const encodeUTF8 = (text: string): Uint8Array => encoder.encode(text);
export const decodeUTF8 = (bytes: Uint8Array): string => decoder.decode(bytes);

export function stripWhitespace(html: string, keepComments?: boolean): string {
let out = html
// reduce whitespace to a single space
.replace(/\s+/gm, ' ')
// remove space between tags
.replace(/> </g, '><')
// remove space between edge and start/end tags
.replace(/^ </g, '<')
.replace(/> $/g, '>')
// remove space around stage1 "node ref tags"
// https://github.com/MaxMilton/stage1
.replace(/> #(\w+) </g, '>#$1<');

if (!keepComments) {
out = out.replace(/<!--.*?-->/gs, '');

Check failure

Code scanning / CodeQL

Incomplete multi-character sanitization

This string may still contain [<!--](1), which may cause a HTML element injection vulnerability.
}

return out;
}

export function minify(code: string, opts: MinifyOptions = {}): MagicString {
const out = new MagicString(code);
const ignoreLines: number[] = [];
Expand Down Expand Up @@ -61,23 +81,11 @@ export function minify(code: string, opts: MinifyOptions = {}): MagicString {
const { start, end } = node.loc;

if (start.line !== end.line || start.column !== end.column) {
let content = node.value.raw
// reduce whitespace to a single space
.replace(/\s+/gm, ' ')
// remove space between tags
.replace(/> </g, '><')
// remove space between edge and start/end tags
.replace(/^ </g, '<')
.replace(/> $/g, '>')
// remove space around stage1 "node ref tags"
// https://github.com/MaxMilton/stage1
.replace(/> #(\w+) </g, '>#$1<');

if (!opts.keepComments) {
content = content.replace(/<!--.*?-->/gs, '');
}

out.overwrite(node.start, node.end, content);
out.overwrite(
node.start,
node.end,
stripWhitespace(node.value.raw, opts.keepComments),
);
}
},
});
Expand Down
1 change: 1 addition & 0 deletions test/exports.test.ts
Expand Up @@ -5,6 +5,7 @@ import * as assert from 'uvu/assert';
import * as allExports from '../src/index';

const publicExports = [
['stripWhitespace', 'function'],
['minify', 'function'],
['minifyTemplates', 'function'],
['writeFiles', 'function'],
Expand Down