@pattern-lab/core
Version:
Create atomic design systems with Pattern Lab. This is the core API and orchestrator of the ecosystem.
171 lines (150 loc) • 5.9 kB
JavaScript
;
const getPartial = require('./get');
const logger = require('./log');
const lineage_hunter = function () {
function findlineage(pattern, patternlab) {
// As we are adding edges from pattern to ancestor patterns, ensure it is known to the graph
patternlab.graph.add(pattern);
//find the {{> template-name }} within patterns
const matches = pattern.findPartials();
if (matches !== null) {
matches.forEach(function (match) {
//get the ancestorPattern
const ancestorPattern = getPartial(
pattern.findPartial(match),
patternlab
);
if (
ancestorPattern &&
pattern.lineageIndex.indexOf(ancestorPattern.patternPartial) === -1
) {
//add it since it didnt exist
pattern.lineageIndex.push(ancestorPattern.patternPartial);
//create the more complex patternLineage object too
const l = {
lineagePattern: ancestorPattern.patternPartial,
lineagePath: '../../patterns/' + ancestorPattern.patternLink,
};
if (ancestorPattern.patternState) {
l.lineageState = ancestorPattern.patternState;
}
patternlab.graph.add(ancestorPattern);
// Confusing: pattern includes "ancestorPattern", not the other way round
patternlab.graph.link(pattern, ancestorPattern);
pattern.lineage.push(l);
//also, add the lineageR entry if it doesn't exist
if (
ancestorPattern.lineageRIndex.indexOf(pattern.patternPartial) === -1
) {
ancestorPattern.lineageRIndex.push(pattern.patternPartial);
//create the more complex patternLineage object in reverse
const lr = {
lineagePattern: pattern.patternPartial,
lineagePath: '../../patterns/' + pattern.patternLink,
};
if (pattern.patternState) {
lr.lineageState = pattern.patternState;
}
ancestorPattern.lineageR.push(lr);
Object.assign(patternlab.graph.node(ancestorPattern), lr);
}
}
});
}
}
/**
* Apply the target pattern state either to any predecessors or successors of the given
* pattern in the pattern graph.
* @param direction Either 'fromPast' or 'fromFuture'
* @param pattern {Pattern}
* @param targetPattern {Pattern}
* @param graph {PatternGraph}
*/
function setPatternState(direction, pattern, targetPattern, graph) {
let index = null;
if (direction === 'fromPast') {
index = graph.lineage(pattern);
} else {
index = graph.lineageR(pattern);
}
// if the request came from the past, apply target pattern state to current pattern lineage
for (let i = 0; i < index.length; i++) {
if (index[i].patternPartial === targetPattern.patternPartial) {
index[i].lineageState = targetPattern.patternState;
}
}
}
function cascadePatternStates(patternlab) {
for (let i = 0; i < patternlab.patterns.length; i++) {
const pattern = patternlab.patterns[i];
//for each pattern with a defined state
if (pattern.patternState) {
const lineage = patternlab.graph.lineage(pattern);
if (lineage && lineage.length > 0) {
//find all lineage - patterns being consumed by this one
for (let h = 0; h < lineage.length; h++) {
setPatternState(
'fromFuture',
lineage[h],
pattern,
patternlab.graph
);
}
}
const lineageR = patternlab.graph.lineageR(pattern);
if (lineageR && lineageR.length > 0) {
//find all reverse lineage - that is, patterns consuming this one
for (let j = 0; j < lineageR.length; j++) {
const lineageRPattern = lineageR[j];
//only set patternState if pattern.patternState "is less than" the lineageRPattern.patternstate
//or if lineageRPattern.patternstate (the consuming pattern) does not have a state
//this makes patternlab apply the lowest common ancestor denominator
const patternStateCascade = patternlab.config.patternStateCascade;
const patternStateIndex = patternStateCascade.indexOf(
pattern.patternState
);
const patternReverseStateIndex = patternStateCascade.indexOf(
lineageRPattern.patternState
);
if (
lineageRPattern.patternState === '' ||
patternStateIndex < patternReverseStateIndex
) {
const oldState =
lineageRPattern.patternState === ''
? '<<blank>>'
: lineageRPattern.patternState;
logger.info(
`Found a lower common denominator pattern state: ${pattern.patternState} on ${pattern.patternPartial}. Setting reverse lineage pattern ${lineageRPattern.patternPartial} from ${oldState}`
);
lineageRPattern.patternState = pattern.patternState;
//take this opportunity to overwrite the lineageRPattern's lineage state too
setPatternState(
'fromPast',
lineageRPattern,
pattern,
patternlab.graph
);
} else {
setPatternState(
'fromPast',
pattern,
lineageRPattern,
patternlab.graph
);
}
}
}
}
}
}
return {
find_lineage: function (pattern, patternlab) {
findlineage(pattern, patternlab);
},
cascade_pattern_states: function (patternlab) {
cascadePatternStates(patternlab);
},
};
};
module.exports = lineage_hunter;