Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"ignore-loader": "^0.1.2",
"mini-css-extract-plugin": "^2.4.5",
"node-fetch": "2.6.7",
"node-polyfill-webpack-plugin": "^1.1.4",
"nodemon-webpack-plugin": "^4.3.1",
"purgecss-webpack-plugin": "^4.1.3",
"raw-loader": "^4.0.2",
Expand Down
9 changes: 9 additions & 0 deletions tests/src/Application.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
display: block;
}


:root {
--custom-var-value: red;
}

.class-\[custom\] {
background: red;
}
Expand All @@ -20,4 +25,8 @@

.should-be-removed {
background: yellow;
}

.\[color\:var\(--custom-var-value\)\] {
color: var(--custom-var-value);
}
2 changes: 2 additions & 0 deletions tests/src/Application.njs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import NestedProxy from './NestedProxy';
import ParentComponent from './ParentComponent';
import PersistentComponent from './PersistentComponent';
import PluginAttributes from './PluginAttributes';
import Polyfill from './Polyfill';
import PublicServerFunctions from './PublicServerFunctions.njs';
import PureComponents from './PureComponents';
import Purge from './Purge';
Expand Down Expand Up @@ -109,6 +110,7 @@ class Application extends Nullstack {
<Purge route="/purge" />
<ComponentTernary route="/component-ternary" />
<AnchorModifiers route="/anchor-modifiers" />
<Polyfill route="/polyfill" />
<ErrorPage route="*" />
</main>
)
Expand Down
65 changes: 65 additions & 0 deletions tests/src/Polyfill.njs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import assert from 'assert';
import buffer from 'buffer';
import console from 'console';
import constants from 'constants';
import crypto from 'crypto';
import domain from 'domain';
import events from 'events';
import http from 'http';
import https from 'https';
import Nullstack from 'nullstack';
import os from 'os';
import path from 'path';
import process from 'process';
import punycode from 'punycode';
import querystring from 'querystring';
import stream from 'stream';
import stringDecoder from 'string_decoder';
import sys from 'sys';
import timers from 'timers';
import tty from 'tty';
import url from 'url';
import util from 'util';
import vm from 'vm';
import zlib from 'zlib';

class Polyfill extends Nullstack {

async hydrate() {
this.buffer = Buffer.from("nullstack").toString()
}

render() {
return (
<div
data-buffer-global={this.buffer}
data-assert={typeof assert}
data-buffer={typeof buffer}
data-console={typeof console}
data-constants={typeof constants}
data-crypto={typeof crypto}
data-domain={typeof domain}
data-events={typeof events}
data-http={typeof http}
data-https={typeof https}
data-os={typeof os}
data-path={typeof path}
data-punycode={typeof punycode}
data-process={typeof process}
data-querystring={typeof querystring}
data-stream={typeof stream}
data-string-decoder={typeof stringDecoder}
data-sys={typeof sys}
data-timers={typeof timers}
data-tty={typeof tty}
data-url={typeof url}
data-util={typeof util}
data-vm={typeof vm}
data-zlib={typeof zlib}
> Polyfill </div>
)
}

}

export default Polyfill;
157 changes: 157 additions & 0 deletions tests/src/Polyfill.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
beforeAll(async () => {
await page.goto('http://localhost:6969/polyfill');
});

describe('Polyfill', () => {

test('client has a polyfill for node buffer global', async () => {
await page.waitForSelector('[data-buffer-global="nullstack"]');
const element = await page.$('[data-buffer-global="nullstack"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node buffer', async () => {
await page.waitForSelector('[data-buffer="object"]');
const element = await page.$('[data-buffer="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node assert', async () => {
await page.waitForSelector('[data-assert="function"]');
const element = await page.$('[data-assert="function"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node console', async () => {
await page.waitForSelector('[data-console="object"]');
const element = await page.$('[data-console="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node constants', async () => {
await page.waitForSelector('[data-constants="object"]');
const element = await page.$('[data-constants="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node crypto', async () => {
await page.waitForSelector('[data-crypto="object"]');
const element = await page.$('[data-crypto="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node domain', async () => {
await page.waitForSelector('[data-domain="object"]');
const element = await page.$('[data-domain="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node events', async () => {
await page.waitForSelector('[data-events="function"]');
const element = await page.$('[data-events="function"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node http', async () => {
await page.waitForSelector('[data-http="object"]');
const element = await page.$('[data-http="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node https', async () => {
await page.waitForSelector('[data-https="object"]');
const element = await page.$('[data-https="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node os', async () => {
await page.waitForSelector('[data-os="object"]');
const element = await page.$('[data-os="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node path', async () => {
await page.waitForSelector('[data-path="object"]');
const element = await page.$('[data-path="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node punycode', async () => {
await page.waitForSelector('[data-punycode="object"]');
const element = await page.$('[data-punycode="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node process', async () => {
await page.waitForSelector('[data-process="object"]');
const element = await page.$('[data-process="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node querystring', async () => {
await page.waitForSelector('[data-querystring="object"]');
const element = await page.$('[data-querystring="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node stream', async () => {
await page.waitForSelector('[data-stream="function"]');
const element = await page.$('[data-stream="function"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node string_decoder', async () => {
await page.waitForSelector('[data-string-decoder="object"]');
const element = await page.$('[data-string-decoder="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node sys', async () => {
await page.waitForSelector('[data-sys="object"]');
const element = await page.$('[data-sys="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node timers', async () => {
await page.waitForSelector('[data-timers="object"]');
const element = await page.$('[data-timers="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node tty', async () => {
await page.waitForSelector('[data-tty="object"]');
const element = await page.$('[data-tty="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node url', async () => {
await page.waitForSelector('[data-url="object"]');
const element = await page.$('[data-url="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node url', async () => {
await page.waitForSelector('[data-url="object"]');
const element = await page.$('[data-url="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node util', async () => {
await page.waitForSelector('[data-util="object"]');
const element = await page.$('[data-util="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node vm', async () => {
await page.waitForSelector('[data-vm="object"]');
const element = await page.$('[data-vm="object"]');
expect(element).toBeTruthy();
});

test('client has a polyfill for node zlib', async () => {
await page.waitForSelector('[data-zlib="object"]');
const element = await page.$('[data-zlib="object"]');
expect(element).toBeTruthy();
});

});
2 changes: 1 addition & 1 deletion tests/src/Purge.njs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Purge extends Nullstack {

render() {
return (
<div class="class class-[custom] class-0.5"> Purge </div>
<div class="class class-[custom] [color:var(--custom-var-value)] class-0.5"> Purge </div>
)
}

Expand Down
5 changes: 5 additions & 0 deletions tests/src/Purge.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ describe('.production', () => {
expect(hasClass).toBeTruthy();
})

test('used classes with arbitraty value and variable stay after purge', async () => {
const hasClass = css.includes('\\[color\\:var\\(--custom-var-value\\)\\]')
expect(hasClass).toBeTruthy();
})

test('used classes with dots stay after purge', async () => {
const hasClass = css.includes('.class-0\\.5')
expect(hasClass).toBeTruthy();
Expand Down
6 changes: 4 additions & 2 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const TerserPlugin = require('terser-webpack-plugin');
const PurgecssPlugin = require('purgecss-webpack-plugin');
const crypto = require("crypto");
const { readdirSync } = require('fs');
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")

const buildKey = crypto.randomBytes(20).toString('hex');

Expand Down Expand Up @@ -216,14 +217,15 @@ function client(env, argv) {
const plugins = [
new MiniCssExtractPlugin({
filename: "client.css"
})
}),
new NodePolyfillPlugin()
]
if (argv.environment === 'production') {
plugins.push(new PurgecssPlugin({
paths: glob.sync(`src/**/*`, { nodir: true }),
content: ['./**/*.njs'],
safelist: ['script', 'body', 'html', 'style'],
defaultExtractor: content => content.match(/[\w-/:\\\.\[\]]+(?<!:)/g) || [],
defaultExtractor: content => content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || [],
}));
}
return {
Expand Down