UNPKG

6.07 kBJavaScriptView Raw
1
2
3/**
4 * This script is supposed to be executed via phantomjs. It will generate
5 * screenshots of the html files in the directory specified by a commandline
6 * option when these files are served through a webserver which can also be
7 * specified. The screenshots will be in the current working directory.
8 *
9 * Example usage:
10 *
11 * user@host:~/openlayers/bin $ phantomjs example-screenshot.js \
12 * http://localhost:8000/openlayers/examples/ \
13 * ../examples
14 *
15 * The above command will generate `*.png` files in `examples/` for all html
16 * files that are served through `http://localhost:8000/openlayers/examples/`.
17 *
18 * So if there is a file `my-humpty-example.html` inside of the relative folder
19 * `../examples/` which is being served through the webserver so that
20 * `http://localhost:8000/openlayers/examples/my-humpty-example.html` is a valid and
21 * reachable URL, this script will generate a screenshot and store it as
22 * `my-humpty-example.html.png`.
23 *
24 * The query string `?mode=raw` will be appended to the generated URL.
25 *
26 * Known limitations:
27 *
28 * As phantomjs doesn't support WebGL (see e.g.
29 * https://github.com/ariya/phantomjs/wiki/Supported-Web-Standards and
30 * http://code.google.com/p/phantomjs/issues/detail?id=273) This won't render
31 * OpenLayers maps rendered through the webglrenderer.
32 *
33 * In parts based upon this gist: https://gist.github.com/crazy4groovy/3160121
34 */
35(function() { // global closure
36
37 var page = require('webpage').create(), // imports
38 fs = require('fs'),
39 system = require('system'),
40 // arguments
41 baseExamplesUrl = system.args[1],
42 exampleDir = system.args[2],
43 // various settings
44 ignoreFiles = [
45 'index.html'
46 ],
47 intervalMillisecs = 25,
48 renderMillisecs = 2000,
49 // basic variables
50 curDir = fs.workingDirectory,
51 exampleDirList = fs.list(exampleDir),
52 pageindex = 0,
53 fileName = '',
54 htmlFiles = [],
55 lenHtmlFiles = 0,
56 loadInProgress = false;
57
58 // simple object with helper functions
59 var util = {
60 /**
61 * Returns the basename of a file given a path.
62 */
63 baseName: function(path) {
64 var parts = path.split(fs.separator);
65 return parts[parts.length - 1];
66 },
67 /**
68 * Super basic test whether a file can be considered a HTML-file.
69 */
70 isHtmlFile: function(filename) {
71 return (/\.html?$/).test(filename);
72 },
73 /**
74 * Appends a slash to given string if it isn't there already.
75 */
76 appendSlash: function(str) {
77 return ((/\/$/).test(str)) ? str : str + '/';
78 },
79 /**
80 * Generates an URL out of given baseurl and path.
81 */
82 buildUrl: function(baseurl, path) {
83 var name = util.baseName(path),
84 mode = 'raw';
85 return util.appendSlash(baseurl) + name + '?mode=' + mode;
86 },
87 /**
88 * Simple progressbar logger that uses our globals pageindex & lenHtmlFiles.
89 */
90 logProgress: function() {
91 var doneSymbol = '-',
92 todoSymbol = ' ',
93 currentSymbol = '>',
94 barStrLeft = '[',
95 barStrRight = ']',
96 progresStep = 5, // one doneSymbol equals this percentage
97 totalSteps = Math.round(100 / progresStep),
98 ratio = (lenHtmlFiles === 0) ? 0 : (pageindex / lenHtmlFiles),
99 percent = (ratio === 0) ? 0 : ratio * 100,
100 normalizedNumDone = Math.floor(ratio * totalSteps),
101 normalizedNumTodo = totalSteps - normalizedNumDone,
102 progressLine = '',
103 i = 0;
104 // the progress bar
105 progressLine += barStrLeft;
106 for (; i < normalizedNumDone; i++) {
107 progressLine += doneSymbol;
108 }
109 for (i = 0; i < normalizedNumTodo; i++) {
110 progressLine += (i === 0) ? currentSymbol : todoSymbol;
111 }
112 progressLine += barStrRight;
113 // the percentage information
114 // pad if necessary
115 if (percent < 10) {
116 progressLine += ' ';
117 } else if (percent < 100) {
118 progressLine += ' ';
119 }
120 progressLine += ' ' + percent.toFixed(1) + ' % done';
121 // additional information
122 if (fileName !== '') {
123 progressLine += ', ' + util.baseName(fileName) + '';
124 }
125 console.log(progressLine);
126 }
127 };
128
129 // iterate over all files in examples directory
130 // and find the HTML files.
131 for (var i = 0; i < exampleDirList.length; i++) {
132 var fullpath = exampleDir + fs.separator + exampleDirList[i];
133 if (fs.isFile(fullpath) && util.isHtmlFile(fullpath) &&
134 ignoreFiles.indexOf(util.baseName(fullpath)) === -1) {
135 //TODO: make this more async (i.e. pop on/off stack WHILE rending pages)
136 htmlFiles.push(fullpath);
137 }
138 }
139 lenHtmlFiles = htmlFiles.length;
140
141 console.log('Capturing ' + lenHtmlFiles + ' example screenshots.');
142
143 // The main interval function that is executed regularly and renders a
144 // page to a file
145 var interval = setInterval(function() {
146 if (!loadInProgress && pageindex < lenHtmlFiles) {
147 util.logProgress();
148 fileName = htmlFiles[pageindex];
149 page.viewportSize = { width: 800, height: 600 };
150 page.clipRect = {
151 top: 0,
152 left: 0,
153 width: page.viewportSize.width,
154 height: page.viewportSize.height
155 };
156 page.open(util.buildUrl(baseExamplesUrl, htmlFiles[pageindex]));
157 }
158 if (pageindex == lenHtmlFiles) {
159 util.logProgress();
160 console.log(lenHtmlFiles + ' screenshots captured.');
161 phantom.exit();
162 }
163 }, intervalMillisecs);
164
165 // set loadInProgress flag so we only process one image at time.
166 page.onLoadStarted = function() {
167 loadInProgress = true;
168 };
169
170 // When the page is loaded, render it to an image
171 page.onLoadFinished = function() {
172 var dest = exampleDir + fs.separator + util.baseName(fileName) + '.png';
173 window.setTimeout(function() {
174 loadInProgress = false;
175 page.render(dest); // actually render the page.
176 pageindex++;
177 }, renderMillisecs);
178 };
179
180})(); // eof global closure