1 | 'use strict';
|
2 |
|
3 | var q = require('q');
|
4 | var request = require('request');
|
5 | var cheerio = require('cheerio');
|
6 |
|
7 | var resolveCssImportUrls = require('resolve-css-import-urls');
|
8 | var getLinkContents = require('./utils/get-link-contents');
|
9 | var createLink = require('./utils/create-link');
|
10 |
|
11 | module.exports = function(url, options){
|
12 |
|
13 | var deferred = q.defer();
|
14 |
|
15 | var options = options || {};
|
16 |
|
17 | var status = {
|
18 | parsed: 0,
|
19 | total: 0
|
20 | }
|
21 |
|
22 | var result = {
|
23 | links: [],
|
24 | styles: [],
|
25 | css: ''
|
26 | };
|
27 |
|
28 | if (options.ignoreCerts) {
|
29 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
30 | }
|
31 |
|
32 | options.timeout = options.timeout || 5000;
|
33 |
|
34 | function handleResolve() {
|
35 | if (status.parsed >= status.total) {
|
36 | deferred.resolve(result);
|
37 | }
|
38 | }
|
39 |
|
40 | function parseHtml(html) {
|
41 | var $ = cheerio.load(html);
|
42 | result.pageTitle = $('title').text();
|
43 |
|
44 | $('[rel=stylesheet]').each(function() {
|
45 | var link = $(this).attr('href');
|
46 | result.links.push(createLink(link, url));
|
47 | });
|
48 |
|
49 | $('style').each(function() {
|
50 | result.styles.push( $(this).text() );
|
51 | });
|
52 |
|
53 | status.total = result.links.length + result.styles.length;
|
54 | if (!status.total) {
|
55 | deferred.resolve(false);
|
56 | }
|
57 |
|
58 | result.links.forEach(function(link) {
|
59 | getLinkContents(link.url, options)
|
60 | .then(function(css) {
|
61 | handleCssFromLink(link, css);
|
62 | })
|
63 | .catch(function(error) {
|
64 | link.error = error;
|
65 | status.parsed++;
|
66 | handleResolve();
|
67 | });
|
68 | });
|
69 |
|
70 | result.styles.forEach(function(css) {
|
71 | result.css += css;
|
72 | status.parsed++;
|
73 | handleResolve();
|
74 | });
|
75 | }
|
76 |
|
77 | function handleCssFromLink(link, css) {
|
78 | link.css += css;
|
79 |
|
80 | parseCssForImports(link, css);
|
81 |
|
82 | status.parsed++;
|
83 | handleResolve();
|
84 | }
|
85 |
|
86 |
|
87 | function parseCssForImports(link, css) {
|
88 | link.imports = resolveCssImportUrls(link.url, css);
|
89 | status.total += link.imports.length;
|
90 | result.css += css;
|
91 |
|
92 | link.imports.forEach(function(importUrl) {
|
93 | var importLink = createLink(importUrl, importUrl);
|
94 | result.links.push(importLink);
|
95 |
|
96 | getLinkContents(importLink.url, options)
|
97 | .then(function(css) {
|
98 | handleCssFromLink(importLink, css);
|
99 | })
|
100 | .catch(function(error) {
|
101 | link.error = error;
|
102 | status.parsed++;
|
103 | handleResolve();
|
104 | });
|
105 | });
|
106 | }
|
107 |
|
108 | request({ url: url, timeout: options.timeout, gzip: true }, function(error, response, body) {
|
109 | if (error) {
|
110 | if (options.verbose) console.log('Error from ' + url + ' ' + error);
|
111 | deferred.reject(error);
|
112 | return;
|
113 | }
|
114 |
|
115 | if (response && response.statusCode != 200) {
|
116 | if (options.verbose) console.log('Received a ' + response.statusCode + ' from: ' + url);
|
117 | deferred.reject({ url: url, statusCode: response.code });
|
118 | return;
|
119 | }
|
120 |
|
121 | parseHtml(body);
|
122 | });
|
123 |
|
124 | return deferred.promise;
|
125 | };
|