Како генерисати ХТМЛ табелу и ПДФ са Ноде и Гоогле Пуппетеер

Цоноце ла тиерра.

Интерно разумевање НодеЈС-а може бити помало застрашујуће (знам да је то некада било за мене). Ноде је веома моћан језик и може да уради много ствари.

Данас сам желео да откријем моћ уграђеног услужног алата Ноде названог фс (систем датотека)

Према фс документима:

fsМодул обезбеђује АПИ за интеракцију са система датотека на начин ближе узору око стандардне функције ПОСИКС.

Што је само измишљен начин да се каже да је систем датотека начин на који Ноде комуницира са датотекама и за операције читања и писања.

Сада је систем датотека огроман услужни програм у НодеЈС-у који има пуно фенси карактеристика. Међутим, у овом чланку ћу говорити само о 3:

  • Добијање података о датотеци: фс.статСинц
  • Брисање датотеке: фс.унлинкСинц
  • Записивање података у датотеку: фс.вритеФилеСинц

Још једна ствар коју ћемо покрити у овом чланку је Гоогле Пуппетеер, који је ово заиста кул, гладак алат који су створили неки сјајни људи на Гооглеу.

Па шта је луткар? Па према документима, они кажу:

Пуппетеер је Ноде библиотека која пружа АПИ на високом нивоу за контролу безглавог Цхроме-а или Цхромиум-а преко протокола ДевТоолс. Такође се може конфигурисати да користи пуни (безглави) Цхроме или Цхромиум.

Дакле, то је у основи алат који вам омогућава да на серверу радите све сјајне ствари повезане са прегледачем. Као што је добијање снимака екрана веб странице, пописивање веб локација и генерисање садржаја који се приказује унапред за апликације на једној страници. Можете чак и да предате обрасце путем вашег НодеЈС сервера.

Луткар је опет огроман алат, тако да ћемо покрити само малу, али врло цоол особину луткара. Погледаћемо како да генеришемо лепу ПДФ датотеку на основу генерисане датотеке ХТМЛ табеле. У процесу ћемо научити о пуппетеер.лаунцх () и разумети мало о страници () и пдф ().

Да бисмо опет дали кратак преглед, ствари које ћемо покрити:

  • Стварање података о оштећењима (за рачуне) помоћу мрежног алата.
  • Креирање ХТМЛ табеле са мало стила са генерисаним подацима у њој, користећи аутоматизовану скрипту чвора.
  • Учење о провери да ли датотека постоји или не помоћу фс.статСинц
  • Учење о брисању датотеке помоћу фс.унлинкСинц
  • Учење о писању датотеке помоћу фс.вритеФилеСинц
  • Прављење ПДФ датотеке од те ХТМЛ датотеке генерисане помоћу Гоогле луткара
  • Претварање у нпм скрипте, које ће касније користити? ?
Такође пре него што започнемо, овде је целокупан изворни код водича, који сви могу да прате. Не морате ништа да пишете, али заједно са овим упутством треба да напишете и код. То ће се показати кориснијим и схватићете више. КОД ИЗВОРА ТУТОРИЈАЛА

Пре него што започнемо, уверите се да сте на машини инсталирали најмање следеће

  • Верзија чвора 8.11.2
  • Ноде Пацкаге Манагер (НПМ) верзија 6.9.0

Не треба, али можете погледати и уводни видео (мој први икада направљен) који говори о основама читања, писања и брисања датотека у НодеЈС-у. Ово ће вам помоћи да разумете овај водич. (Молим вас, дајте ми повратне информације). ?

Хајде да почнемо

Корак 1:

У свој терминал унесите следеће:

npm init -y

Ово ће покренути празан пројекат за вас.

Корак 2:

Друго, у истој фасцикли направите нову датотеку која се зове data.jsonи у њој ће бити неких исмеваних података. Можете користити следећи ЈСОН узорак.

Подмећане ЈСОН податке о калупу можете добити одавде . За генерисање ових података користио сам сјајан алат назван //моцкароо.цом/ То је алат за генерирање података на мрежи.

ЈСОН подаци са којима идем имају структуру попут ове:

[ {}, {}, { "invoiceId": 1, "createdDate": "3/27/2018", "dueDate": "5/24/2019", "address": "28058 Hazelcrest Center", "companyName": "Eayo", "invoiceName": "Carbonated Water - Peach", "price": 376 }, { "invoiceId": 2, "createdDate": "6/14/2018", "dueDate": "11/14/2018", "address": "6205 Shopko Court", "companyName": "Ozu", "invoiceName": "Pasta - Fusili Tri - Coloured", "price": 285 }, {}, {} ]
Комплетни ЈСОН низ за овај водич можете преузети овде .

Корак 3:

Затим створите нову датотеку под називом buildPaths.js

const path = require('path'); const buildPaths = { buildPathHtml: path.resolve('./build.html'), buildPathPdf: path.resolve('./build.pdf') }; module.exports = buildPaths;

Тако path.resolveће узети релативни пут и вратити нам апсолутни пут тог одређеног директорија.

Тако path.resolve('./build.html');ће на пример вратити нешто овако:

$ C:\\Users\\Adeel\\Desktop\\articles\\tutorial\\build.html

Корак 4:

У истом директоријуму креирајте датотеку која се зове createTable.jsи додајте следећи код:

const fs = require('fs'); // JSON data const data = require('./data.json'); // Build paths const { buildPathHtml } = require('./buildPaths'); /** * Take an object which has the following model * @param {Object} item * @model * { * "invoiceId": `Number`, * "createdDate": `String`, * "dueDate": `String`, * "address": `String`, * "companyName": `String`, * "invoiceName": `String`, * "price": `Number`, * } * * @returns {String} */ const createRow = (item) => ` ${item.invoiceId}${item.invoiceName}${item.price}${item.createdDate}${item.dueDate}${item.address}${item.companyName} `; /** * @description Generates an `html` table with all the table rows * @param {String} rows * @returns {String} */ const createTable = (rows) => ` 
     ${rows} 
     
Invoice Id Invoice Name Price Invoice Created Due Date Vendor Address Vendor Name
`; /** * @description Generate an `html` page with a populated table * @param {String} table * @returns {String} */ const createHtml = (table) => ` table { width: 100%; } tr { text-align: left; border: 1px solid black; } th, td { padding: 15px; } tr:nth-child(odd) { background: #CCC } tr:nth-child(even) { background: #FFF } .no-content { background-color: red; } ${table} `; /** * @description this method takes in a path as a string & returns true/false * as to if the specified file path exists in the system or not. * @param {String} filePath * @returns {Boolean} */ const doesFileExist = (filePath) => { try { fs.statSync(filePath); // get information of the specified file path. return true; } catch (error) { return false; } }; try { /* Check if the file for `html` build exists in system or not */ if (doesFileExist(buildPathHtml)) { console.log('Deleting old build file'); /* If the file exists delete the file from system */ fs.unlinkSync(buildPathHtml); } /* generate rows */ const rows = data.map(createRow).join(''); /* generate table */ const table = createTable(rows); /* generate html */ const html = createHtml(table); /* write the generated html to file */ fs.writeFileSync(buildPathHtml, html); console.log('Succesfully created an HTML table'); } catch (error) { console.log('Error generating table', error); }

I know that is a lot of code, but let’s divide it into chunks and start understanding it piece by piece.

Go to line 106 (github gist)

In our try/catch block we first check if the build file for HTML exists in the system or not. This is the path of the file where our NodeJS script will generate our HTML.

if (doesFileExist(buildPathHtml){} calls doesFileExist() method which simply returns true/false. For this we use

fs.statSync(filePath);

This method actually returns information about the file like the size of the file, when the file was created, and so on. However if we provide it an invalid file path, this method returns as a null error. Which we use here to our benefit and wrap the fs.statSync() method in a try/catch. If Node is successfully able to read the file in our try block, we return true — otherwise it throws an error which we get in our catch block and returns false.

If the file exists in the system we end up deleting the file using

fs.unlinkSync(filePath); // takes in a file path & deletes it

After deleting the file, we need to generate rows to put in the table.

Step 5:

So first we import data.json which we do at line 3 & then on line 115 we iterate each item using map(). You can read more about Array.prototype.map() here.

The map method takes a method createRow which takes in an object through each iteration and returns a string which has content like this:

"invoice idinvoice nameinvoice priceinvoice created dateinvoice due dateinvoice addressinvoice sender company name"
const row = data.map(createdRow).join('');

The join('') part is important here, because I want to concatenate all of my array into a string.

An almost similar principle is used for generating a table on line 117 & then the html table on line 119.

Step 6:

The important part is where we write to our file on line 121:

fs.writeFileSync(buildPathHtml, html); 

It takes in 2 parameters: one is the build path (string) and the html content (string) and generates a file (if not created; and if it is created, it overwrites the already existing file).

Овде треба напоменути једну ствар која нам можда неће требати 4. корак, где проверавамо да ли датотека постоји и ако постоји, онда је обришемо. То је зато што вритеФилеСинц то ради за нас. Управо сам то додао у код за потребе учења.

Корак 7:

У свом терминалу идите на путању до фасцикле на којој имате createTable.jsи тип

$ npm run ./createTable.js

Чим покренете ову скрипту, створиће нову датотеку у истој фасцикли под називом build.htmlМожете је отворити у свом прегледачу и изгледаће отприлике овако.

Цоол зар не? Засада је добро. ?

Такође npm scriptу свој пакет.јсон можете додати овако:

"scripts": { "build:table": "node ./createTable.js" },

На овај начин, уместо писања npm run ./createTable.js, можете само да укуцате npm run build:table.

Следеће: генерисање ПДФ-а из генерисане HTMLдатотеке.

Корак 8:

First things first we need to install a fancy tool, so go in your terminal in your application folder and type in

npm install puppeteer

Step 9:

In the same folder where you have files createTable.js , buildPaths.js & data.json, create a new file called createPdf.js and add content to it like below:

 const fs = require('fs'); const puppeteer = require('puppeteer'); // Build paths const { buildPathHtml, buildPathPdf } = require('./buildPaths'); const printPdf = async () => { console.log('Starting: Generating PDF Process, Kindly wait ..'); /** Launch a headleass browser */ const browser = await puppeteer.launch(); /* 1- Ccreate a newPage() object. It is created in default browser context. */ const page = await browser.newPage(); /* 2- Will open our generated `.html` file in the new Page instance. */ await page.goto(buildPathHtml, { waitUntil: 'networkidle0' }); /* 3- Take a snapshot of the PDF */ const pdf = await page.pdf({ format: 'A4', margin: { top: '20px', right: '20px', bottom: '20px', left: '20px' } }); /* 4- Cleanup: close browser. */ await browser.close(); console.log('Ending: Generating PDF Process'); return pdf; }; const init = async () => { try { const pdf = await printPdf(); fs.writeFileSync(buildPathPdf, pdf); console.log('Succesfully created an PDF table'); } catch (error) { console.log('Error generating PDF', error); } }; init();

As we did with createTable.js script, let’s break this down into chunks and start understanding this script step by step.

Let’s start with line 40: here we call a method init() which calls the method on line 30. Onething to focus on is that our init() method is an async method. Read more on this async function.

Прво у методи инит () називамо методу принтПдф () која је опет асинхронска метода, па морамо сачекати њен одговор. Метода принтПдф () враћа нам ПДФ инстанцу коју затим записујемо у датотеку у реду 33.

Па, шта printPdf()метода ради? Копајмо дубоко у то.

const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(buildPathHtml, { waitUntil: 'networkidle0' }); const pdf = await page.pdf({ format: 'A4', margin: { top: '20px', right: '20px', bottom: '20px', left: '20px'} }); await browser.close(); return pdf;

Прво покрећемо безглаву инстанцу прегледача помоћу луткарства радећи следеће:

await puppeteer.launch(); // this returns us headless browser

коју затим користимо за отварање веб странице:

await browser.newPage(); // open a blank page in headless browser

Једном када отворимо празну страницу, можемо доћи до странице. Пошто је наша веб страница локално у нашем систему, ми једноставно

page.goto(buildPathHtml, { waitUntil: 'networkidle0' });

Овде waitUntil: 'networkidle0;је важно, јер луткару говори да сачека 500 / мс док више нема мрежних веза.

Напомена: Због тога смо користили патх.ресолве () да бисмо добили апсолутне путање, јер да бисмо отворили веб страницу са луткаром, потребан нам је апсолутни пут.

After we have a web page opened in the headless browser on the server, we save that page as a pdf:

await page.pdf({ });

As soon as we have a pdf version of the web page, we need to close the browser instance opened by puppeteer to save resources by doing this:

await browser.close();

& then we return the pdf saved, which we then write to the file.

Step 10:

In your terminal type

$ npm ./createPdf.js

Note: Before running the above script, ensure that you the build.html file generated by createTable.js script. This ensures we always have the build.html prior to running the createPdf.js script. In your package,json do the following.

"scripts": { "build:table": "node ./createTable.js", "prebuild:pdf": "npm run build:table", "build:pdf": "node ./createPdf.js" },

Now if you run $ npm run build:pdf it will execute the createTable.js script first and then createPdf.js script. You can read more on NPM scripts on their official docs.

When you run

$ npm run build:pdf

It will run and create a build.pdf which will look like this:

И то је то, готови смо.

Научили сте следеће:

  • Како проверити да ли датотека постоји / информације о тет датотеци (у Ноде)
  • Како избрисати датотеку у Ноде-у
  • Како писати у датотеку
  • Како се користи Гоогле Пуппетеер за генерисање ПДФ датотеке

Срећно учење, волео бих да чујем ваше мисли о овом чланку. Можете ме добити на Твиттерутакође.