Skip to content

Commit

Permalink
feat(list_item_hunter): Re-work algorithm
Browse files Browse the repository at this point in the history
Now list_item_hunter does almost nothing, transforming the spec syntax into a friendly single value (rather than nested with a period), so that we can ALSO transform listItem data into the same structure - meaning `2` in the json becomes `listItem-two` - which can very easily by looped over by mustache. this change should be further vetted
  • Loading branch information
bmuenzenmeyer committed Jan 19, 2018
1 parent c722868 commit 1ac77a7
Show file tree
Hide file tree
Showing 13 changed files with 288 additions and 702 deletions.
40 changes: 33 additions & 7 deletions core/lib/buildListItems.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
'use strict';

const _ = require('lodash');
let _ = require('lodash'); //eslint-disable-line prefer-const

const items = [
'zero',
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
'ten',
'eleven',
'twelve',
'thirteen',
'fourteen',
'fifteen',
'sixteen',
'seventeen',
'eighteen',
'nineteen',
'twenty',
];

module.exports = function(container) {
//combine all list items into one structure
Expand All @@ -10,17 +34,19 @@ module.exports = function(container) {
list.push(container.listitems[item]);
}
}
container.listItemArray = _.shuffle(list);
const listItemArray = _.shuffle(list);

for (let i = 1; i <= container.listItemArray.length; i++) {
for (let i = 1; i <= listItemArray.length; i++) {
const tempItems = [];
if (i === 1) {
tempItems.push(container.listItemArray[0]);
container.listitems['' + i] = tempItems;
tempItems.push(listItemArray[0]);
container.listitems['listItems-' + items[i]] = tempItems;
delete container.listitems[i];
} else {
for (let c = 1; c <= i; c++) {
tempItems.push(container.listItemArray[c - 1]);
container.listitems['' + i] = tempItems;
tempItems.push(listItemArray[c - 1]);
container.listitems['listItems-' + items[i]] = tempItems;
delete container.listitems[i];
}
}
}
Expand Down
246 changes: 20 additions & 226 deletions core/lib/list_item_hunter.js
Original file line number Diff line number Diff line change
@@ -1,244 +1,38 @@
'use strict';

const list_item_hunter = function() {
const extend = require('util')._extend;
const _ = require('lodash');
const smh = require('./style_modifier_hunter');
const jsonCopy = require('./json_copy');
const Pattern = require('./object_factory').Pattern;

const logger = require('./log');
const parseLink = require('./parseLink');
const getPartial = require('./get');
const render = require('./render');

const style_modifier_hunter = new smh();
const items = [
'zero',
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
'ten',
'eleven',
'twelve',
'thirteen',
'fourteen',
'fifteen',
'sixteen',
'seventeen',
'eighteen',
'nineteen',
'twenty',
];

function processListItemPartials(pattern, patternlab) {
function processListItemPartials(pattern) {
//find any listitem blocks
const matches = pattern.findListItems();

if (matches !== null) {
return matches.reduce((previousMatchPromise, liMatch) => {
return matches.reduce((previousMatchPromise, liMatchStart) => {
return previousMatchPromise.then(() => {
logger.debug(
`found listItem of size ${liMatch} inside ${pattern.patternPartial}`
`found listItem of size ${liMatchStart} inside ${
pattern.patternPartial
}`
);

//find the boundaries of the block
const loopNumberString = liMatch
.split('.')[1]
.split('}')[0]
.trim();
const end = liMatch.replace('#', '/');
const patternBlock = pattern.template
.substring(
pattern.template.indexOf(liMatch) + liMatch.length,
pattern.template.indexOf(end)
)
.trim();

//build arrays that repeat the block, however large we need to
const repeatedBlockTemplate = [];

//what we will eventually replace our template's listitems block with
let repeatedBlockHtml = '';

for (let i = 0; i < items.indexOf(loopNumberString); i++) {
logger.debug(
`list item(s) in pattern ${
pattern.patternPartial
}, adding ${patternBlock} to repeatedBlockTemplate`
);
repeatedBlockTemplate.push(patternBlock);
}

//check for a local listitems.json file
let listData;
try {
listData = jsonCopy(
patternlab.listitems,
'config.paths.source.data listitems'
);
} catch (err) {
logger.warning(
`There was an error parsing JSON for ${pattern.relPath}`
);
logger.warning(err);
}

listData = _.merge(listData, pattern.listitems);
listData = parseLink(
patternlab,
listData,
'listitems.json + any pattern listitems.json'
//we found a listitem match
//replace it's beginning listitems.number with -number
const newStart = liMatchStart.replace('.', '-');
pattern.extendedTemplate = pattern.extendedTemplate.replace(
liMatchStart,
newStart
);

//iterate over each copied block, rendering its contents
const allBlocks = repeatedBlockTemplate.reduce(
(previousPromise, currentBlockTemplate, index) => {
let thisBlockTemplate = currentBlockTemplate;

return previousPromise
.then(() => {
//combine listItem data with pattern data with global data
const itemData =
listData['' + items.indexOf(loopNumberString)]; //this is a property like "2"
let globalData;
let localData;
try {
globalData = jsonCopy(
patternlab.data,
'config.paths.source.data global data'
);
localData = jsonCopy(
pattern.jsonFileData,
`${pattern.patternPartial} data`
);
} catch (err) {
logger.warning(
`There was an error parsing JSON for ${pattern.relPath}`
);
logger.warning(err);
}

let allData = _.merge(globalData, localData);
allData = _.merge(
allData,
itemData !== undefined ? itemData[index] : {}
); //itemData could be undefined if the listblock contains no partial, just markup
allData.link = extend({}, patternlab.data.link);

//check for partials within the repeated block
const foundPartials = Pattern.createEmpty({
template: thisBlockTemplate,
}).findPartials();

let renderPromise = undefined;

if (foundPartials && foundPartials.length > 0) {
for (let j = 0; j < foundPartials.length; j++) {
//get the partial
const partialName = foundPartials[j].match(
/([\w\-\.\/~]+)/g
)[0];
const partialPattern = getPartial(
partialName,
patternlab
);

//create a copy of the partial so as to not pollute it after the get_pattern_by_key call.
let cleanPartialPattern;
try {
cleanPartialPattern = JSON.parse(
JSON.stringify(partialPattern)
);
cleanPartialPattern = jsonCopy(
partialPattern,
`partial pattern ${partialName}`
);
} catch (err) {
logger.warning(
`There was an error parsing JSON for ${
pattern.relPath
}`
);
logger.warning(err);
}

//if we retrieved a pattern we should make sure that its extendedTemplate is reset. looks to fix #356
cleanPartialPattern.extendedTemplate =
cleanPartialPattern.template;

//if partial has style modifier data, replace the styleModifier value
if (foundPartials[j].indexOf(':') > -1) {
style_modifier_hunter.consume_style_modifier(
cleanPartialPattern,
foundPartials[j],
patternlab
);
}

//replace its reference within the block with the extended template
thisBlockTemplate = thisBlockTemplate.replace(
foundPartials[j],
cleanPartialPattern.extendedTemplate
);
}

//render with data
renderPromise = render(
Pattern.createEmpty({ template: thisBlockTemplate }),
allData,
patternlab.partials
);
} else {
//just render with mergedData
renderPromise = render(
Pattern.createEmpty({ template: thisBlockTemplate }),
allData,
patternlab.partials
);
}

return renderPromise
.then(thisBlockHTML => {
//add the rendered HTML to our string
repeatedBlockHtml = repeatedBlockHtml + thisBlockHTML;
})
.catch(reason => {
logger.error(reason);
});
})
.catch(reason => {
logger.error(reason);
});
},
Promise.resolve()
//replace it's ending listitems.number with -number
const liMatchEnd = liMatchStart.replace('#', '/');
const newEnd = liMatchEnd.replace('.', '-');
pattern.extendedTemplate = pattern.extendedTemplate.replace(
liMatchEnd,
newEnd
);

return allBlocks
.then(() => {
//replace the block with our generated HTML
const repeatingBlock = pattern.extendedTemplate.substring(
pattern.extendedTemplate.indexOf(liMatch),
pattern.extendedTemplate.indexOf(end) + end.length
);
pattern.extendedTemplate = pattern.extendedTemplate.replace(
repeatingBlock,
repeatedBlockHtml
);

//update the extendedTemplate in the partials object in case this pattern is consumed later
patternlab.partials[pattern.patternPartial] =
pattern.extendedTemplate;
})
.catch(reason => {
logger.error(reason);
});
return Promise.resolve();
});
}, Promise.resolve());
} else {
Expand All @@ -247,8 +41,8 @@ const list_item_hunter = function() {
}

return {
process_list_item_partials: function(pattern, patternlab) {
return processListItemPartials(pattern, patternlab);
process_list_item_partials: function(pattern) {
return processListItemPartials(pattern);
},
};
};
Expand Down
18 changes: 11 additions & 7 deletions core/lib/patternlab.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const packageInfo = require('../../package.json');
const buildListItems = require('./buildListItems');
const dataLoader = require('./data_loader')();
const logger = require('./log');
const parseLink = require('./parseLink');
const processIterative = require('./processIterative');
const processRecursive = require('./processRecursive');
const jsonCopy = require('./json_copy');
Expand Down Expand Up @@ -363,13 +364,16 @@ module.exports = class PatternLab {

//render the pattern, but first consolidate any data we may have
let allData;
try {
allData = jsonCopy(this.data, 'config.paths.source.data global data');
} catch (err) {
logger.info('There was an error parsing JSON for ' + pattern.relPath);
logger.info(err);
}
allData = _.merge(allData, pattern.jsonFileData);

let allListItems = _.merge({}, this.listitems, pattern.listitems);
allListItems = parseLink(
this,
allListItems,
'listitems.json + any pattern listitems.json'
);

allData = _.merge({}, this.data, pattern.jsonFileData);
allData = _.merge({}, allData, allListItems);
allData.cacheBuster = this.cacheBuster;

///////////////
Expand Down
Loading

0 comments on commit 1ac77a7

Please sign in to comment.