UNPKG

draw-page-structure

Version:

a nice tool to make skeleton screen

160 lines (146 loc) 4.78 kB
const fs = require('fs'); const path = require('path'); const cheerio = require('cheerio'); const ppteer = require('./pp'); const defaultHtml = require('./default.html'); const evalScripts = require('../evalDOM'); const { log, getAgrType, Spinner, calcText, genArgs } = require('./utils'); const currDir = process.cwd(); class DrawPageStructure { constructor({ url, output = {}, background, animation, rootNode, header, device, headless, extraHTTPHeaders, writePageStructure, includeElement, init } = {}) { let filepath = !output.filepath || path.isAbsolute(output.filepath) ? output.filepath : path.join(currDir, output.filepath); this.url = url; this.filepath = filepath; this.injectSelector = output.injectSelector || 'body'; this.background = background || '#ecf0f2'; this.animation = animation || ''; this.rootNode = rootNode || ''; this.header = header || ''; this.device = device; this.headless = headless; this.extraHTTPHeaders = extraHTTPHeaders; this.writePageStructure = writePageStructure; this.includeElement = includeElement || function() {}; this.init = init || function() {}; if (this.headless === undefined) this.headless = true; if (!url) { log.error('please provide entry url !', 1); } if (header && getAgrType(header) !== 'object') { log.error('[header] should be an object !', 1); } if (filepath) { if (!fs.existsSync(filepath)) { log.error('[output.filepath:404] please provide the output filepath !', 1); } else { const fileStat = fs.statSync(filepath); if (fileStat.isDirectory()) { filepath = path.join(filepath, 'index.html'); fs.writeFileSync(filepath, defaultHtml); this.filepath = filepath; } } } } async generateSkeletonHTML(page) { let html = ''; try { // html = await page.evaluate.call( // page, // evalScripts, // this.init.toString(), // this.includeElement.toString(), // this.background, // this.animation, // this.rootNode, // this.header // ); const agrs = genArgs.create({ init: { type: 'function', value: this.init.toString() }, includeElement: { type: 'function', value: this.includeElement.toString() }, background: { type: 'string', value: this.background }, animation: { type: 'string', value: this.animation }, rootNode: { type: 'string', value: this.rootNode }, header: { type: 'object', value: JSON.stringify(this.header) } }); agrs.unshift(evalScripts); html = await page.evaluate.apply(page, agrs); } catch (e) { log.error('\n[page.evaluate] ' + e.message); } return html; } writeToFilepath(filepath, html) { let fileHTML = fs.readFileSync(filepath); let $ = cheerio.load(fileHTML, { decodeEntities: false }); $(this.injectSelector).html(html); fs.writeFileSync(filepath, $.html('html')); } async start() { const pageUrl = this.url; const spinner = Spinner('magentaBright'); spinner.text = '启动浏览器...'; const pp = await ppteer({ device: this.device, headless: this.headless }); spinner.text = `正在打开页面:${ pageUrl }...`; const page = await pp.openPage(pageUrl, this.extraHTTPHeaders); spinner.text = '正在生成骨架屏...'; const html = await this.generateSkeletonHTML(page); const userWrite = getAgrType(this.writePageStructure) === 'function'; if (userWrite) { this.writePageStructure(html, this.filepath); } if (this.filepath) { this.writeToFilepath(this.filepath, html); } if (!userWrite && !this.filepath) { const defaultPage = path.join(currDir, 'index.html'); fs.writeFileSync(defaultPage, defaultHtml); this.writeToFilepath(defaultPage, html); this.filepath = defaultPage; spinner.clear(); log.warn(`\nskeleton has created in a default page: ${defaultPage}`); } spinner.clear().succeed(`skeleton screen has created and output to ${calcText(this.filepath)}`); if (this.headless) { await pp.browser.close(); process.exit(0); } } } module.exports = DrawPageStructure;