The provided code appears to be part of a template rendering engine that processes Google Sheets data, utilizing functions from the importer
object to load, process, and render templates. It includes functions like getTemplateProperties
and matchSections
that recursively process template properties and sections, respectively.
npm run import -- "google sheet template properties"
var importer = require('../Core');
var getDataSheet = importer.import("google sheet array objects");
var renderRows = importer.import("google sheet layout template");
var getRows = importer.import("get worksheet rows");
var {filteredData, unfilteredData} = importer.import("filter data sheet based on url");
var promiseOrResolve = importer.import("resolve promise property");
var isWrapper = rows => rows.length === 1 && rows[0].length === 1
&& rows[0][0].match(/\{\{\s*>\s*(.*?)(\/(.*?-)+link)*\}\}/ig);
var isFiltered = (url) => url.split('/').length > 1
// TODO: remove previous properties if for some strange reason recalling the same template,
// prevents situations like ::stylesheet being added to many times
var addedProperties = {};
function getTemplateProperties(key, properties, templates) {
if(typeof templates[key] === 'undefined') {
throw new Error(`section "${key}" not found!`)
}
// load template data
var rows;
return promiseOrResolve(templates[key].data, 'rows', getDataSheet)
.then(data => {
properties[key + '-original-data'] = data;
properties[key + '-data'] = unfilteredData.bind(null, key);
})
// load template layout
.then(() => promiseOrResolve(templates[key].template, 'rows', getRows))
.then(rs => {
rows = rs || []
return rows.flat()
.reduce((p, c, j) => p.then(() => matchSections(c, properties, templates)), Promise.resolve())
})
// detect if this is just a wrapper template and don't render rows, do a direct replacement
.then(() => isWrapper(rows) ? rows[0][0] : renderRows(key, rows, properties, templates))
.then(template => (properties[key] = template))
}
// must do this up front so we can process all data
var matchSections = (cell, properties, templates) => importer
.regexToArray(/\{\{\s*>\s*(.*?)\s*\}\}/ig, cell, 1)
.reduce((promise, section) => promise
.then(() => getTemplateProperties(section.split('/')[0], properties, templates))
.then(() => isFiltered(section)
? createAssignFilter(section, properties)
: Promise.resolve()),
Promise.resolve())
var isCategorical = (data, key) => data.filter(row => row.hasOwnProperty(key)).length > 0;
function createAssignFilter(section, properties) {
var key = section.split('/')[0];
var match = section.split('/').slice(1).join('/');
properties[section] = properties[key];
// add a special partial for the filtered data
var categorical = isCategorical(properties[key + '-original-data'] || [], key)
// automatically wrap unique templates in a data section for accessing filtered properties
if(!categorical && !properties[key].includes(`{{#${key}-data}}`)
&& typeof properties[key + '-original-data'] !== 'undefined') {
properties[section] = `{{#${key}-data}}${properties[key]}{{/${key}-data}}`;
}
// run the filtered function instead of using the array
properties[key + '-data'] = filteredData.bind(null, key, match, properties, categorical);
}
module.exports = getTemplateProperties;
// Import required modules
const { getDataSheet, renderRows, getRows, filteredData, unfilteredData } = require('../Core');
// Define a function to check if a row is a wrapper template
const isWrapper = rows => rows.length === 1 && rows[0].length === 1
&& rows[0][0].match(/\{\{\s*>\s*(.*?)(\/(.*?-)+link)*\}\}/ig);
// Define a function to check if a URL is filtered
const isFiltered = (url) => url.split('/').length > 1;
// Define a function to get template properties
const getTemplateProperties = async (key, properties, templates, getDataSheet, renderRows, getRows, filteredData, unfilteredData) => {
if (!templates[key]) {
throw new Error(`Section "${key}" not found!`);
}
// Load template data
const data = await promiseOrResolve(templates[key].data, 'rows', getDataSheet);
properties[key + '-original-data'] = data;
properties[key + '-data'] = unfilteredData.bind(null, key);
// Load template layout
const rows = await promiseOrResolve(templates[key].template, 'rows', getRows);
const flatRows = rows.flat();
// Detect if this is just a wrapper template and don't render rows, do a direct replacement
if (isWrapper(flatRows)) {
return flatRows[0][0];
}
// Render rows
const template = await renderRows(key, flatRows, properties, templates);
properties[key] = template;
return properties;
};
// Define a function to match sections
const matchSections = async (cell, properties, templates, getDataSheet, renderRows, getRows, filteredData, unfilteredData) => {
const sections = importer.regexToArray(/\{\{\s*>\s*(.*?)\s*\}\}/ig, cell, 1);
return sections.reduce(async (promise, section) => {
const result = await promise;
const key = section.split('/')[0];
// Check if the section is filtered
if (isFiltered(section)) {
return createAssignFilter(section, properties);
}
// Get template properties
const properties = await getTemplateProperties(key, properties, templates, getDataSheet, renderRows, getRows, filteredData, unfilteredData);
return Promise.resolve(properties);
}, Promise.resolve(properties));
};
// Define a function to create an assign filter
const createAssignFilter = (section, properties) => {
const key = section.split('/')[0];
const match = section.split('/').slice(1).join('/');
properties[section] = properties[key];
// Add a special partial for the filtered data
const categorical = isCategorical(properties[key + '-original-data'] || [], key);
// Automatically wrap unique templates in a data section for accessing filtered properties
if (!categorical &&!properties[key].includes(`{{#${key}-data}}`) && typeof properties[key + '-original-data']!== 'undefined') {
properties[section] = `{{#${key}-data}}${properties[key]}{{/${key}-data}}`;
}
// Run the filtered function instead of using the array
properties[key + '-data'] = filteredData.bind(null, key, match, properties, categorical);
};
// Define a function to check if data is categorical
const isCategorical = (data, key) => data.filter(row => row.hasOwnProperty(key)).length > 0;
// Export the getTemplateProperties function
module.exports = async (key, properties, templates, getDataSheet, renderRows, getRows, filteredData, unfilteredData) => {
return getTemplateProperties(key, properties, templates, getDataSheet, renderRows, getRows, filteredData, unfilteredData);
};
Code Breakdown
importer
: an object that provides various functions from the ../Core
module.getDataSheet
, renderRows
, getRows
, and filteredData
: functions imported from the importer
object.promiseOrResolve
: a function imported from the importer
object, used to resolve promises.isWrapper
and isFiltered
: functions that check if a given data is a wrapper template or if a URL is filtered.This function retrieves template properties from a given key and updates the properties object. Here's a step-by-step breakdown:
templates
object. If not, throws an error.promiseOrResolve
to load the template data from the getDataSheet
function.unfilteredData
function to the key and stores the data in the properties object.promiseOrResolve
to load the template layout from the getRows
function.reduce
to process each row. If the row matches a wrapper template, it returns the row as a single element. Otherwise, it renders the rows using the renderRows
function.This function matches sections in a cell and recursively calls getTemplateProperties
to process each section. Here's a step-by-step breakdown:
importer.regexToArray
to extract sections from the cell.getTemplateProperties
for each section and returns a promise chain.isWrapper
: Checks if a given data is a wrapper template by matching a specific regex pattern.isFiltered
: Checks if a URL is filtered by checking if it has more than one '/' character.The code appears to be part of a template rendering engine that processes Google Sheets data. It uses a combination of functions from the importer
object to load and process data, update properties, and render templates.