UNPKG

n8n-nodes-base

Version:

Base nodes of n8n

262 lines 11.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.HtmlExtract = void 0; const cheerio_1 = __importDefault(require("cheerio")); const get_1 = __importDefault(require("lodash/get")); const n8n_workflow_1 = require("n8n-workflow"); // The extraction functions const extractFunctions = { attribute: ($, valueData) => $.attr(valueData.attribute), html: ($, _valueData) => $.html() || undefined, text: ($, _valueData) => $.text(), value: ($, _valueData) => $.val(), }; /** * Simple helper function which applies options */ function getValue($, valueData, options) { const value = extractFunctions[valueData.returnValue]($, valueData); if (options.trimValues === false || value === undefined) { return value; } return value.trim(); } class HtmlExtract { description = { displayName: 'HTML Extract', name: 'htmlExtract', icon: 'fa:cut', group: ['transform'], version: 1, hidden: true, subtitle: '={{$parameter["sourceData"] + ": " + $parameter["dataPropertyName"]}}', description: 'Extracts data from HTML', defaults: { name: 'HTML Extract', color: '#333377', }, inputs: [n8n_workflow_1.NodeConnectionTypes.Main], outputs: [n8n_workflow_1.NodeConnectionTypes.Main], properties: [ { displayName: 'Source Data', name: 'sourceData', type: 'options', options: [ { name: 'Binary', value: 'binary', }, { name: 'JSON', value: 'json', }, ], default: 'json', description: 'If HTML should be read from binary or JSON data', }, { displayName: 'Input Binary Field', name: 'dataPropertyName', type: 'string', displayOptions: { show: { sourceData: ['binary'], }, }, default: 'data', required: true, hint: 'The name of the input binary field containing the file to be extracted', }, { displayName: 'JSON Property', name: 'dataPropertyName', type: 'string', displayOptions: { show: { sourceData: ['json'], }, }, default: 'data', required: true, description: 'Name of the JSON property in which the HTML to extract the data from can be found. The property can either contain a string or an array of strings.', }, { displayName: 'Extraction Values', name: 'extractionValues', placeholder: 'Add Value', type: 'fixedCollection', typeOptions: { multipleValues: true, }, default: {}, options: [ { name: 'values', displayName: 'Values', values: [ { displayName: 'Key', name: 'key', type: 'string', default: '', description: 'The key under which the extracted value should be saved', }, { displayName: 'CSS Selector', name: 'cssSelector', type: 'string', default: '', placeholder: '.price', description: 'The CSS selector to use', }, { displayName: 'Return Value', name: 'returnValue', type: 'options', options: [ { name: 'Attribute', value: 'attribute', description: 'Get an attribute value like "class" from an element', }, { name: 'HTML', value: 'html', description: 'Get the HTML the element contains', }, { name: 'Text', value: 'text', description: 'Get only the text content of the element', }, { name: 'Value', value: 'value', description: 'Get value of an input, select or textarea', }, ], default: 'text', description: 'What kind of data should be returned', }, { displayName: 'Attribute', name: 'attribute', type: 'string', displayOptions: { show: { returnValue: ['attribute'], }, }, default: '', placeholder: 'class', description: 'The name of the attribute to return the value off', }, { displayName: 'Return Array', name: 'returnArray', type: 'boolean', default: false, description: 'Whether to return the values as an array so if multiple ones get found they also get returned separately. If not set all will be returned as a single string.', }, ], }, ], }, { displayName: 'Options', name: 'options', type: 'collection', placeholder: 'Add option', default: {}, options: [ { displayName: 'Trim Values', name: 'trimValues', type: 'boolean', default: true, description: 'Whether to remove automatically all spaces and newlines from the beginning and end of the values', }, ], }, ], }; async execute() { const items = this.getInputData(); const returnData = []; let item; for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { try { const dataPropertyName = this.getNodeParameter('dataPropertyName', itemIndex); const extractionValues = this.getNodeParameter('extractionValues', itemIndex); const options = this.getNodeParameter('options', itemIndex, {}); const sourceData = this.getNodeParameter('sourceData', itemIndex); item = items[itemIndex]; let htmlArray = []; if (sourceData === 'json') { const data = (0, get_1.default)(item.json, dataPropertyName, undefined); if (data === undefined) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No property named "${dataPropertyName}" exists!`, { itemIndex }); } htmlArray = data; } else { this.helpers.assertBinaryData(itemIndex, dataPropertyName); const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(itemIndex, dataPropertyName); htmlArray = binaryDataBuffer.toString('utf-8'); } // Convert it always to array that it works with a string or an array of strings if (!Array.isArray(htmlArray)) { htmlArray = [htmlArray]; } for (const html of htmlArray) { const $ = cheerio_1.default.load(html); const newItem = { json: {}, pairedItem: { item: itemIndex, }, }; // Iterate over all the defined values which should be extracted let htmlElement; for (const valueData of extractionValues.values) { htmlElement = $(valueData.cssSelector); if (valueData.returnArray) { // An array should be returned so iterate over one // value at a time newItem.json[valueData.key] = []; htmlElement.each((_, el) => { newItem.json[valueData.key].push(getValue($(el), valueData, options)); }); } else { // One single value should be returned newItem.json[valueData.key] = getValue(htmlElement, valueData, options); } } returnData.push(newItem); } } catch (error) { if (this.continueOnFail()) { returnData.push({ json: { error: error.message, }, pairedItem: { item: itemIndex, }, }); continue; } throw error; } } return [returnData]; } } exports.HtmlExtract = HtmlExtract; //# sourceMappingURL=HtmlExtract.node.js.map