Skip to content
This repository was archived by the owner on Mar 9, 2021. It is now read-only.

Commit c472db7

Browse files
committed
Adds JSDOM mode
1 parent 3de8bfc commit c472db7

File tree

9 files changed

+315
-84
lines changed

9 files changed

+315
-84
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ glyphhanger ./test.html --json
5555
# show results only for one or more font-family names
5656
glyphhanger ./test.html --family='Open Sans, Roboto'
5757

58+
# use much faster jsdom mode instead of headless Chrome
59+
glyphhanger ./test.html --jsdom
60+
5861
# Show version
5962
glyphhanger --version
6063

@@ -209,6 +212,13 @@ Limit results to text inside of elements that match a CSS selector
209212
glyphhanger ./test.html --cssSelector="pre, #header, .popUp". If paired with `--onlyVisible`, it will only return elements that are both visible and match the selector
210213
```
211214

215+
### Advanced: use `jsdom` Mode ⚠️
216+
217+
JSDOM mode can be useful running against static pages that don’t use a lot of JavaScript generated content. While JSDOM mode can handle some JavaScript generated content, Puppeteer mode should be the safest method for most use cases.
218+
219+
JSDOM mode will also be much faster when running against files on a local filesystem rather than URL targets.
220+
221+
Read more about [the difference between JSDOM and a full headless browser](https://github.com/jsdom/jsdom/wiki/jsdom-vs.-PhantomJS) (like the default mode that glyphhanger uses: Puppeteer/headless Chrome).
212222

213223
## Troubleshooting
214224

cmd.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#!/usr/bin/env node
22
var argv = require( "minimist" )( process.argv.slice(2) );
33
var GlyphHanger = require( "./src/GlyphHanger" );
4-
var GlyphHangerFormat = require( "./src/GlyphHangerFormat" );
54
var GlyphHangerWhitelist = require( "./src/GlyphHangerWhitelist" );
65
var GlyphHangerSubset = require( "./src/GlyphHangerSubset" );
76
var GlyphHangerFontFace = require( "./src/GlyphHangerFontFace" );
@@ -23,6 +22,9 @@ gh.setFamilies( argv.family );
2322
gh.setTimeout( argv.timeout );
2423
gh.setVisibilityCheck( argv.onlyVisible );
2524
gh.setCSSSelector( argv.cssSelector );
25+
if( argv.jsdom ) {
26+
gh.setEnvironmentJSDOM();
27+
}
2628

2729
var subset = new GlyphHangerSubset();
2830
subset.setOutputDirectory(argv.output);
@@ -89,12 +91,12 @@ if( argv.version ) {
8991
}
9092

9193
gh.output();
92-
9394
try {
9495
fontface.setUnicodeRange( gh.getUnicodeRange() );
9596
fontface.writeCSSFiles();
9697
} catch(e) {
9798
console.log("GlyphHangerFontFace Error: ", e);
99+
process.exit(1);
98100
}
99101

100102
try {
@@ -103,13 +105,17 @@ if( argv.version ) {
103105
}
104106
} catch(e) {
105107
console.log("GlyphHangerSubset Error: ", e);
108+
process.exit(1);
106109
}
107110

108111
try {
109112
fontface.output();
110113
} catch(e) {
111114
console.log("GlyphHangerFontFace Error: ", e);
115+
process.exit(1);
112116
}
117+
118+
process.exit();
113119
})();
114120
} else { // not using URLs
115121
if( argv.subset ) {
@@ -119,6 +125,7 @@ if( argv.version ) {
119125
// --subset with or without --whitelist
120126
subset.subsetAll( !whitelist.isEmpty() ? whitelist.getWhitelistAsUnicodes() : whitelist.getUniversalRangeAsUnicodes() );
121127
} catch(e) {
128+
process.exitCode = 1;
122129
console.log("GlyphHangerSubset Error: ", e);
123130
}
124131

@@ -129,6 +136,7 @@ if( argv.version ) {
129136
fontface.writeCSSFiles();
130137
fontface.output();
131138
} catch(e) {
139+
process.exitCode = 1;
132140
console.log("GlyphHangerFontFace Error: ", e);
133141
}
134142
} else if( !whitelist.isEmpty() ) {
@@ -140,6 +148,7 @@ if( argv.version ) {
140148
fontface.writeCSSFiles();
141149
fontface.output();
142150
} catch(e) {
151+
process.exitCode = 1;
143152
console.log("GlyphHangerFontFace Error: ", e);
144153
}
145154
} else {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"shelljs": "^0.7.8"
4040
},
4141
"devDependencies": {
42-
"jsdom": "^11.5.1",
42+
"jsdom": "^13.0.0",
4343
"mocha": "^4.0.1"
4444
}
4545
}

src/GlyphHanger.js

Lines changed: 27 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
const chalk = require( "chalk" );
2-
const path = require( "path" );
3-
const puppeteer = require('puppeteer');
42
const CharacterSet = require( "characterset" );
53
const WebServer = require( "./WebServer" );
64
const GlyphHangerWhitelist = require( "./GlyphHangerWhitelist" );
5+
const GlyphHangerEnvironment = require( "./GlyphHangerEnvironment" );
76
const debug = require("debug")("glyphhanger");
8-
const debugNodes = require("debug")("glyphhanger:nodes");
97

108
class GlyphHanger {
119
constructor() {
@@ -16,14 +14,11 @@ class GlyphHanger {
1614
this.timeout = 30000;
1715
this.onlyVisible = false;
1816
this.whitelist = new GlyphHangerWhitelist();
17+
this.env = new GlyphHangerEnvironment();
1918
}
2019

21-
async getBrowser() {
22-
if( !this.browser ) {
23-
this.browser = await puppeteer.launch();
24-
}
25-
26-
return this.browser;
20+
setEnvironmentJSDOM() {
21+
this.env.setEnvironment("jsdom");
2722
}
2823

2924
setSubset( subset ) {
@@ -112,74 +107,24 @@ class GlyphHanger {
112107
return set;
113108
}
114109

115-
async _getPage(url) {
116-
let browser = await this.getBrowser();
117-
let page = await browser.newPage();
118-
page.setBypassCSP(true);
119-
120-
try {
121-
let response = await page.goto(url, {
122-
waitUntil: ["load", "networkidle0"],
123-
timeout: this.timeout
124-
});
125-
126-
let statusCode = response.status();
127-
128-
if ( statusCode !== 200 ) {
129-
console.log(chalk.yellow(`Warning: ${url} had a non 200 HTTP status code: (${statusCode})`));
130-
}
131-
132-
return page;
133-
} catch(e) {
134-
console.log(chalk.red(`Error with ${url}:`), e);
135-
}
110+
getOptions() {
111+
return {
112+
className: this.className,
113+
onlyVisible: this.onlyVisible,
114+
cssSelector: this.cssSelector
115+
};
136116
}
137117

138118
async _fetchUrl( url ) {
139119
debug( "requesting: %o", url );
140120

141-
let page = await this._getPage(url);
121+
let page = await this.env.getPage(url);
142122

143123
if(!page) {
144124
return false;
145125
}
146-
147-
page.on("console", function(msg) {
148-
debugNodes("(headless browser console): %o", msg.text());
149-
});
150-
151-
await page.addScriptTag({
152-
path: require.resolve("characterset")
153-
});
154-
155-
await page.addScriptTag({
156-
path: path.resolve(__dirname, "../src/glyphhanger-script.js")
157-
});
158-
159-
// debugNodes("Full document.body.innerHTML:");
160-
// debugNodes(await page.evaluate( function() {
161-
// return document.body.innerHTML;
162-
// }));
163-
164-
let json = await page.evaluate( function(docClassName, opts) {
165-
if(docClassName && docClassName !== "undefined") {
166-
// add to both the documentElement and document.body because why not
167-
document.documentElement.className += " " + docClassName;
168-
169-
if( "body" in document ) {
170-
document.body.className += " " + docClassName;
171-
}
172-
}
173-
174-
var hanger = new GlyphHanger();
175-
hanger.init( document.body, opts );
176-
177-
return hanger.toJSON();
178-
}, this.className, {
179-
onlyVisible: this.onlyVisible,
180-
cssSelector: this.cssSelector
181-
}
182-
);
126+
let options = this.getOptions();
127+
let json = await this.env.getResults(page, options);
183128

184129
debug("Adding to set for %o: %o", url, json);
185130
this.addToSets(json);
@@ -190,14 +135,18 @@ class GlyphHanger {
190135
for( let url of urls ) {
191136
debug("WebServer.isValidUrl(%o)", url);
192137

193-
if(!WebServer.isValidUrl(url) || url.indexOf('http://localhost:') === 0 ) {
194-
if( !this.staticServer ) {
195-
debug("Creating static server");
196-
this.staticServer = await WebServer.getStaticServer();
138+
let urlStr = url;
139+
if(this.env.requiresWebServer()) {
140+
if(!WebServer.isValidUrl(url) || url.indexOf('http://localhost:') === 0 ) {
141+
if( !this.staticServer ) {
142+
debug("Creating static server");
143+
this.staticServer = await WebServer.getStaticServer();
144+
}
197145
}
146+
147+
urlStr = WebServer.getUrl(url);
198148
}
199149

200-
let urlStr = WebServer.getUrl(url);
201150
if( (await this._fetchUrl(urlStr)) === false ) {
202151
failCount++;
203152
}
@@ -207,11 +156,12 @@ class GlyphHanger {
207156
console.log( chalk.red( `${failCount} of ${urls.length} urls failed.` ) );
208157
}
209158

210-
let browser = await this.getBrowser();
211-
await browser.close();
159+
await this.env.close();
212160

213-
debug("Closing static server");
214-
WebServer.close(this.staticServer);
161+
if(this.env.requiresWebServer()) {
162+
debug("Closing static server");
163+
WebServer.close(this.staticServer);
164+
}
215165
}
216166

217167
getOutputForSet(set) {

0 commit comments

Comments
 (0)