@pattern-lab/core
Version:
Create atomic design systems with Pattern Lab. This is the core API and orchestrator of the ecosystem.
937 lines (856 loc) • 33.6 kB
JavaScript
;
const path = require('path');
const _ = require('lodash');
const Pattern = require('./object_factory').Pattern;
const logger = require('./log');
const uikitExcludePattern = require('./uikitExcludePattern');
// these are mocked in unit tests, so let them be overridden
let render = require('./render'); //eslint-disable-line prefer-const
let fs = require('fs-extra'); //eslint-disable-line prefer-const
let buildFooter = require('./buildFooter'); //eslint-disable-line prefer-const
let exportData = require('./exportData'); //eslint-disable-line prefer-const
const ui_builder = function () {
/**
* Registers the pattern to the patternPaths object for the appropriate patternGroup and basename
* patternGroup + patternBaseName are what comprise the patternPartial (atoms-colors)
* @param patternlab - global data store
* @param pattern - the pattern to add
*/
function addToPatternPaths(patternlab, pattern) {
if (!patternlab.patternPaths[pattern.patternGroup]) {
patternlab.patternPaths[pattern.patternGroup] = {};
}
// only add real patterns
if (pattern.isPattern && !pattern.isDocPattern) {
patternlab.patternPaths[pattern.patternGroup][pattern.patternBaseName] =
pattern.name;
}
}
/**
* Registers the pattern with the viewAllPaths object for the appropriate patternGroup and patternSubgroup
* @param patternlab - global data store
* @param pattern - the pattern to add
*/
function addToViewAllPaths(patternlab, pattern) {
if (!patternlab.viewAllPaths[pattern.patternGroup]) {
patternlab.viewAllPaths[pattern.patternGroup] = {};
}
if (
!patternlab.viewAllPaths[pattern.patternGroup][pattern.patternSubgroup] &&
pattern.patternSubgroup
) {
// note these retain any number prefixes if present, because these paths match the filesystem
patternlab.viewAllPaths[pattern.patternGroup][
pattern.patternSubgroup
] = `${pattern.patternGroup}-${pattern.patternSubgroup}`;
}
// add all if it does not exist yet
if (!patternlab.viewAllPaths[pattern.patternGroup].all) {
patternlab.viewAllPaths[pattern.patternGroup].all = pattern.patternGroup;
}
}
/**
* Returns whether or not the pattern should be excluded from direct rendering or navigation on the front end
* @param pattern - the pattern to test for inclusion/exclusion
* @param patternlab - global data store
* @param uikit - the current uikit being built
* @returns boolean - whether or not the pattern is excluded
*/
function isPatternExcluded(pattern, patternlab, uikit) {
let isOmitted;
// skip patterns that the uikit does not want to render
isOmitted = uikitExcludePattern(pattern, uikit);
if (isOmitted) {
logger.info(
`Omitting ${pattern.patternPartial} from styleguide patterns because its pattern state or tag is excluded within ${uikit.name}.`
);
return true;
}
// skip marked as hidden patterns
isOmitted =
(pattern.isPattern && pattern.hidden) ||
// TODO: Remove next line when removing support & deprecation waring for underscore prefix hiding
(pattern.isPattern && pattern.fileName.charAt(0) === '_');
if (isOmitted) {
logger.info(
`Omitting ${pattern.patternPartial} from styleguide patterns because it is marked as hidden within it's documentation.`
);
return true;
}
// this is meant to be a homepage that is not present anywhere else
isOmitted = pattern.patternPartial === patternlab.config.defaultPattern;
if (isOmitted) {
logger.info(
`Omitting ${pattern.patternPartial} from styleguide patterns because it is defined as a defaultPattern.`
);
patternlab.defaultPattern = pattern;
return true;
}
// this pattern is contained with a directory documented as hidden (a handy way to hide whole directories from the nav
isOmitted =
(pattern.patternGroupData && pattern.patternGroupData.hidden) ||
(pattern.patternSubgroupData && pattern.patternSubgroupData.hidden) ||
// TODO: Remove next two lines when removing support & deprecation waring for underscore prefix hiding
pattern.relPath.charAt(0) === '_' ||
pattern.relPath.indexOf(path.sep + '_') > -1;
if (isOmitted) {
logger.info(
`Omitting ${pattern.patternPartial} from styleguide patterns because its contained within an hidden directory.`
);
return true;
}
// this pattern is a head or foot pattern
isOmitted = pattern.isMetaPattern;
if (isOmitted) {
logger.info(
`Omitting ${pattern.patternPartial} from styleguide patterns because its a meta pattern.`
);
return true;
}
// yay, let's include this on the front end
return isOmitted;
}
/**
* For the given pattern, find or construct the view-all pattern block for the group
* @param pattern - the pattern to derive our documentation pattern from
* @param patternlab - global data store
* @param isSubgroupPattern - whether or not this is a subgroupPattern or a typePattern (groupedPatterns not supported yet)
* @returns the found or created pattern object
*/
function injectDocumentationBlock(pattern, patternlab, isSubgroupPattern) {
return new Pattern.createEmpty(
{
name: pattern.flatPatternPath,
patternName: _.startCase(
isSubgroupPattern ? pattern.patternSubgroup : pattern.patternGroup
),
patternDesc: isSubgroupPattern
? pattern.patternSubgroupData.markdown
: pattern.patternGroupData.markdown,
patternPartial: `viewall-${pattern.patternGroup}-${
isSubgroupPattern ? pattern.patternSubgroup : 'all'
}`,
patternSectionSubgroup: true,
patternLink: path.join(
isSubgroupPattern ? pattern.flatPatternPath : pattern.patternGroup,
'index.html'
),
isPattern: false,
engine: null,
flatPatternPath: pattern.flatPatternPath,
isDocPattern: true,
order: Number.MIN_SAFE_INTEGER,
},
patternlab
);
}
/**
* Sorts the given patterns in the way they are ment to be sorted
* @param {array} patterns which should be sorted
* @returns a sorted array of patterns
*/
function getSortedPatterns(patterns) {
return _.sortBy(patterns, ['order', 'variantOrder', 'name']);
}
/**
* Registers flat patterns with the patternGroups object
* This is a new menu group like atoms
* @param patternlab - global data store
* @param pattern - the pattern to register
*/
function addPatternGroup(patternlab, pattern) {
patternlab.patternGroups.push({
patternGroupLC: _.kebabCase(pattern.patternGroup),
patternGroupUC: _.startCase(pattern.patternGroup),
patternGroup: pattern.patternGroup,
patternGroupDash: pattern.patternGroup, //todo verify
patternGroupItems: [],
order:
pattern.patternGroupData && pattern.patternGroupData.order
? Number(pattern.patternGroupData.order)
: 0,
});
patternlab.patternGroups = _.sortBy(
patternlab.patternGroups,
'order',
'patternGroup'
);
}
/**
* Return the patternGroup object for the given pattern. Exits application if not found.
* @param patternlab - global data store
* @param pattern - the pattern to derive the pattern Type from
* @returns the found pattern type object
*/
function getPatternGroup(patternlab, pattern) {
const patternGroup = _.find(patternlab.patternGroups, [
'patternGroup',
pattern.patternGroup,
]);
if (!patternGroup) {
logger.error(
`Could not find patternGroup ${pattern.patternGroup}. This is a critical error.`
);
}
return patternGroup;
}
/**
* Return the patternSubgroup object for the given pattern. Exits application if not found.
* @param patternlab - global data store
* @param pattern - the pattern to derive the pattern subgroup from
* @returns the found patternSubgroup object
*/
function getPatternSubgroup(patternlab, pattern) {
const patternGroup = getPatternGroup(patternlab, pattern);
const patternSubgroup = _.find(patternGroup.patternGroupItems, [
'patternSubgroup',
pattern.patternSubgroup,
]);
if (!patternSubgroup) {
logger.error(
`Could not find patternGroup ${pattern.patternGroup}-${pattern.patternGroup}. This is a critical error.`
);
}
return patternSubgroup;
}
/**
* Registers the pattern with the appropriate patternGroup.patternGroupItems object
* This is a new menu group like atoms/global
* @param patternlab - global data store
* @param pattern - the pattern to register
*/
function addPatternSubgroup(patternlab, pattern) {
const patternGroup = getPatternGroup(patternlab, pattern);
patternGroup.patternGroupItems.push({
patternSubgroupLC: _.kebabCase(pattern.patternSubgroup),
patternSubgroupUC: _.startCase(pattern.patternSubgroup),
patternSubgroup: pattern.patternSubgroup,
patternSubgroupDash: pattern.patternSubgroup, //todo verify
patternSubgroupItems: [],
order:
pattern.patternSubgroupData && pattern.patternSubgroupData.order
? Number(pattern.patternSubgroupData.order)
: 0,
});
patternGroup.patternGroupItems = _.sortBy(
patternGroup.patternGroupItems,
'order',
'patternSubgroup'
);
}
/**
* Creates a patternSubgroupItem object from a pattern
* This is a menu item you click on
* @param pattern - the pattern to derive the subgroupitem from
* @returns {{patternPartial: string, patternName: (*|string), patternState: string, patternPath: string}}
*/
function createPatternSubgroupItem(pattern) {
return {
patternPartial: pattern.patternPartial,
patternName: pattern.patternName,
patternState: pattern.patternState,
patternPath: pattern.patternLink,
name: pattern.name,
isDocPattern: false,
order: Number(pattern.order) || 0, // Failsafe is someone entered a string
variantOrder: Number(pattern.variantOrder) || 0, // Failsafe is someone entered a string
};
}
/**
* Registers the pattern with the appropriate patternGroup.patternSubgroup.patternSubgroupItems array
* These are the actual menu items you click on
* @param patternlab - global data store
* @param pattern - the pattern to derive the subgroupitem from
* @param createViewAllVariant - whether or not to create the special view all item
*/
function addPatternSubgroupItem(
patternlab,
pattern,
createSubgroupViewAllVariant
) {
let newSubgroupItem;
if (createSubgroupViewAllVariant) {
newSubgroupItem = {
patternPartial:
'viewall-' + pattern.patternGroup + '-' + pattern.patternSubgroup,
patternName: `View All`,
patternPath: encodeURI(pattern.flatPatternPath + '/index.html'),
patternGroup: pattern.patternGroup,
patternSubgroup: pattern.patternSubgroup,
name: pattern.flatPatternPath,
isDocPattern: true,
order: Number.MAX_SAFE_INTEGER,
};
} else {
newSubgroupItem = createPatternSubgroupItem(pattern);
}
const patternSubgroup = getPatternSubgroup(patternlab, pattern);
patternSubgroup.patternSubgroupItems.push(newSubgroupItem);
patternSubgroup.patternSubgroupItems = getSortedPatterns(
patternSubgroup.patternSubgroupItems
);
}
/**
* Registers flat patterns to the appropriate type
* @param patternlab - global data store
* @param pattern - the pattern to add
*/
function addPatternItem(patternlab, pattern, isViewAllVariant) {
const patternGroup = getPatternGroup(patternlab, pattern);
if (!patternGroup) {
logger.error(
`Could not find patternGroup ${pattern.patternGroup}. This is a critical error.`
);
}
patternGroup.patternItems = patternGroup.patternItems || [];
if (isViewAllVariant) {
patternGroup.patternItems.push({
patternPartial: `viewall-${pattern.patternGroup}-all`,
patternName: `View all ${_.startCase(pattern.patternGroup)}`,
patternPath: encodeURI(pattern.patternGroup + '/index.html'),
name: pattern.patternGroup,
isDocPattern: true,
order: Number.MAX_SAFE_INTEGER, // Or pattern.groupData.order
});
} else {
patternGroup.patternItems.push(createPatternSubgroupItem(pattern));
}
patternGroup.patternItems = getSortedPatterns(patternGroup.patternItems);
}
/**
* Returns an object representing how the front end styleguide and navigation is structured
* @param patternlab - global data store
* @param uikit - the current uikit being built
* @returns patterns grouped by type -> subgroup like atoms -> global -> pattern, pattern, pattern
*/
function groupPatterns(patternlab, uikit) {
const groupedPatterns = {
patternGroups: {},
};
_.forEach(patternlab.patterns, function (pattern) {
// ignore patterns we can omit from rendering directly
pattern.omitFromStyleguide = isPatternExcluded(
pattern,
patternlab,
uikit
);
if (pattern.omitFromStyleguide) {
return;
}
if (!groupedPatterns.patternGroups[pattern.patternGroup]) {
groupedPatterns.patternGroups[pattern.patternGroup] = {};
pattern.isSubgroupPattern = false;
addPatternGroup(patternlab, pattern);
if (
!pattern.isFlatPattern ||
patternlab.config.renderFlatPatternsOnViewAllPages
) {
addPatternItem(patternlab, pattern, true);
}
addToViewAllPaths(patternlab, pattern);
}
// continue building navigation for nested patterns
if (!pattern.isFlatPattern) {
if (
!groupedPatterns.patternGroups[pattern.patternGroup][
pattern.patternSubgroup
]
) {
addPatternSubgroup(patternlab, pattern);
pattern.isSubgroupPattern = !pattern.isPattern;
groupedPatterns.patternGroups[pattern.patternGroup][
pattern.patternSubgroup
] = {};
groupedPatterns.patternGroups[pattern.patternGroup][
pattern.patternSubgroup
]['viewall-' + pattern.patternGroup + '-' + pattern.patternSubgroup] =
injectDocumentationBlock(pattern, patternlab, true);
addToViewAllPaths(patternlab, pattern);
addPatternSubgroupItem(patternlab, pattern, true);
}
groupedPatterns.patternGroups[pattern.patternGroup][
pattern.patternSubgroup
][pattern.patternBaseName] = pattern;
addToPatternPaths(patternlab, pattern);
addPatternSubgroupItem(patternlab, pattern);
} else {
addPatternItem(patternlab, pattern);
addToPatternPaths(patternlab, pattern);
}
});
return groupedPatterns;
}
/**
* Search all flat patterns of a specific pattern type
*
* @param {Patternlab} patternlab Current patternlab instance
* @param {string} patternGroup indicator which patterns to search for
*/
function getFlatPatternItems(patternlab, patternGroup) {
const patterns = _.filter(
patternlab.patterns,
(pattern) =>
pattern.patternGroup === patternGroup && pattern.isFlatPattern
);
if (patterns) {
return getSortedPatterns(patterns);
}
return [];
}
/**
* Takes a set of patterns and builds a viewall HTML page for them
* Used by the type and subgroup viewall sets
* @param patternlab - global data store
* @param patterns - the set of patterns to build the viewall page for
* @param patternPartial - a key used to identify the viewall page
* @returns A promise which resolves with the HTML
*/
function buildViewAllHTML(patternlab, patterns, patternPartial, uikit) {
return render(
Pattern.createEmpty({ extendedTemplate: uikit.viewAll }, patternlab),
{
// data
partials: patterns,
patternPartial: 'viewall-' + patternPartial,
cacheBuster: patternlab.cacheBuster,
},
{
// templates
patternSection: uikit.patternSection,
patternSectionSubgroup: uikit.patternSectionSubgroup,
}
).catch((reason) => {
console.log(reason);
logger.error('Error building buildViewAllHTML');
});
}
/**
* Sorts the pattern groups for the view all page as they are meant to be sorted.
* Therefore the function searches for the subgroup in the patternGroupItems and retrieves its sorting.
* @param patternGroup The pattern group object with it's subgroups
* @param patternGroupName the pattern group name e.g. atoms
* @param patternlab - global data store
* @returns a sorted list of pattern groups
*/
function getSortedPatternSubgroups(
patternGroup,
patternGroupName,
patternlab
) {
return _.sortBy(_.values(patternGroup), [
(pSubgroup) => {
const group = patternlab.patternGroups.find(
(g) => g.patternGroup === patternGroupName
);
if (group) {
const sg = group.patternGroupItems.find((item) => {
const firstPattern = _.first(
_.values(pSubgroup).filter((p) => p.patternBaseName !== '.')
);
return (
item &&
firstPattern &&
firstPattern.patternSubgroup === item.patternSubgroup
);
});
return sg ? sg.order : 0;
} else {
return 0;
}
},
]);
}
/**
* Constructs viewall pages for each set of grouped patterns
* @param mainPageHeadHtml - the already built main page HTML
* @param patternlab - global data store
* @param styleguidePatterns - the grouped set of patterns
* @returns every built pattern and set of viewall patterns, so the styleguide can use it
*/
function buildViewAllPages(
mainPageHeadHtml,
patternlab,
styleguidePatterns,
uikit
) {
const paths = patternlab.config.paths;
let patterns = [];
// loop through the grouped styleguide patterns, building at each level
const allPatternGroupPromises = _.map(
patternlab.patternGroups,
(patternGroup) => {
const patternGroupName = patternGroup.patternGroup;
const group = styleguidePatterns.patternGroups[patternGroupName];
let groupedPatterns = [];
let styleguideGroupedPatterns = [];
const styleGuideExcludes = patternlab.config.styleGuideExcludes || [];
/**
* View all pages for subgroups
*/
const subgroupPromises = _.map(
getSortedPatternSubgroups(group, patternGroupName, patternlab),
(patternSubgroups, patternSubgroup, originalPatternGroup) => {
let p;
const samplePattern = _.find(
patternSubgroups,
(st) => !st.patternPartial.startsWith('viewall-')
);
const patternName = Object.keys(
_.values(originalPatternGroup)[patternSubgroup]
)[1];
const patternPartial =
patternGroupName + '-' + samplePattern.patternSubgroup;
// do not create a viewall page for flat patterns
if (patternGroupName === patternName) {
logger.debug(
`skipping ${patternGroupName} as flat patterns do not have view all pages`
);
return Promise.resolve();
}
// render the footer needed for the viewall template
return buildFooter(patternlab, `viewall-${patternPartial}`, uikit)
.then((footerHTML) => {
// render the viewall template by finding these smallest subgroup-grouped patterns
const subgroupPatterns = getSortedPatterns(
_.values(patternSubgroups)
);
// determine if we should write at this time by checking if these are flat patterns or grouped patterns
p = _.find(subgroupPatterns, function (pat) {
return pat.isDocPattern;
});
// determine if we should omit this subpatternGroup completely from the viewall page
const omitPatternGroup =
styleGuideExcludes &&
styleGuideExcludes.length &&
_.some(
styleGuideExcludes,
(exclude) =>
exclude === `${patternGroupName}/${patternName}`
);
if (omitPatternGroup) {
logger.debug(
`Omitting ${patternGroupName}/${patternName} from building a viewall page because its patternSubgroup is specified in styleguideExcludes.`
);
} else {
styleguideGroupedPatterns =
styleguideGroupedPatterns.concat(subgroupPatterns);
}
groupedPatterns = groupedPatterns.concat(subgroupPatterns);
// render the viewall template for the subgroup
return buildViewAllHTML(
patternlab,
subgroupPatterns,
patternPartial,
uikit
)
.then((viewAllHTML) => {
return fs.outputFile(
path.join(
process.cwd(),
uikit.outputDir,
path.join(
`${paths.public.patterns}${p.flatPatternPath}`,
'index.html'
)
),
mainPageHeadHtml + viewAllHTML + footerHTML
);
})
.catch((reason) => {
console.log(reason);
logger.error('Error building ViewAllHTML');
});
})
.catch((reason) => {
console.log(reason);
logger.error('Error building footer HTML');
});
}
);
/**
* View all pages for groups
*/
return Promise.all(subgroupPromises)
.then(() => {
// render the footer needed for the viewall template
return buildFooter(
patternlab,
`viewall-${patternGroupName}-all`,
uikit
)
.then((footerHTML) => {
const sortedFlatPatterns = getFlatPatternItems(
patternlab,
patternGroupName
);
if (patternlab.config.renderFlatPatternsOnViewAllPages) {
// Check if this is a flat pattern group
groupedPatterns = sortedFlatPatterns.concat(groupedPatterns);
}
// get the appropriate patternGroup
const anyPatternOfType = _.find(
groupedPatterns,
function (pat) {
return pat.patternGroup && pat.patternGroup !== '';
}
);
if (!anyPatternOfType || !groupedPatterns.length) {
logger.debug(
`skipping ${patternGroupName} as flat patterns do not have view all pages`
);
return Promise.resolve([]);
}
// render the viewall template for the type
return buildViewAllHTML(
patternlab,
groupedPatterns,
patternGroupName,
uikit
)
.then((viewAllHTML) => {
fs.outputFileSync(
path.join(
process.cwd(),
uikit.outputDir,
path.join(
`${paths.public.patterns}${patternGroupName}`,
'index.html'
)
),
mainPageHeadHtml + viewAllHTML + footerHTML
);
// determine if we should omit this patternGroup completely from the viewall page
const omitPatternGroup =
styleGuideExcludes &&
styleGuideExcludes.length &&
_.some(styleGuideExcludes, function (exclude) {
return exclude === patternGroupName;
});
if (omitPatternGroup) {
logger.debug(
`Omitting ${patternGroupName} from building a viewall page because its patternGroup is specified in styleguideExcludes.`
);
} else {
if (patternlab.config.renderFlatPatternsOnViewAllPages) {
patterns = sortedFlatPatterns;
patterns = patterns.concat(styleguideGroupedPatterns);
} else {
patterns = styleguideGroupedPatterns;
}
}
return Promise.resolve(patterns);
})
.catch((reason) => {
console.log(reason);
logger.error('Error building ViewAllHTML');
});
})
.catch((reason) => {
console.log(reason);
logger.error('Error building footerHTML');
});
})
.catch((reason) => {
console.log(reason);
logger.error('Error during buildViewAllPages');
});
}
);
return Promise.all(allPatternGroupPromises)
.then((allPatterns) =>
Promise.resolve(_.filter(allPatterns, (p) => p.length))
)
.catch((reason) => {
console.log(reason);
logger.error('Error during buildViewAllPages');
});
}
/**
* Reset any global data we use between builds to guard against double adding things
*
* @param {Patternlab} patternlab Actual patternlab instance
*/
function resetUIBuilderState(patternlab) {
patternlab.patternPaths = {};
patternlab.viewAllPaths = {};
patternlab.patternGroups = [];
}
/**
* Uniques all generated patterns and groups, also adds a group document pattern before
* each group. Used for generating view all page and all its pattern.
*
* @param {[Pattern[]]} allPatterns All generated patterns
* @param {Patternlab} patternlab Actual patternlab instance
*/
function uniqueAllPatterns(allPatterns, patternlab) {
return _.uniq(
_.flatMapDeep(
_.map(allPatterns, (patterns) => [
injectDocumentationBlock(
_.find(patterns, (p) => !p.patternPartial.startsWith('viewall-')),
patternlab,
false
),
...patterns,
]),
(pattern) => pattern
)
);
}
/**
* The main entry point for ui_builder
* @param patternlabGlobal - global data store
* @returns {Promise} a promise fulfilled when build is complete
*/
function buildFrontend(patternlabGlobal) {
const paths = patternlabGlobal.config.paths;
const uikitPromises = _.map(patternlabGlobal.uikits, (uikit) => {
//we need to make sure the patternlab object gets manipulated per uikit
const patternlab = Object.assign({}, patternlabGlobal);
resetUIBuilderState(patternlab);
//determine which patterns should be included in the front-end rendering
const styleguidePatterns = groupPatterns(patternlab, uikit);
return new Promise((resolve) => {
// set the pattern-specific header by compiling the general-header with data, and then adding it to the meta header
const headerPromise = render(
Pattern.createEmpty({ extendedTemplate: uikit.header }, patternlab),
{
cacheBuster: patternlab.cacheBuster,
}
)
.then((headerPartial) => {
const headFootData = patternlab.data;
headFootData.patternLabHead = headerPartial;
headFootData.cacheBuster = patternlab.cacheBuster;
return render(patternlab.userHead, headFootData);
})
.catch((reason) => {
console.log(reason);
logger.error('error during header render()');
});
// set the pattern-specific footer by compiling the general-footer with data, and then adding it to the meta footer
const footerPromise = render(
Pattern.createEmpty({ extendedTemplate: uikit.footer }, patternlab),
{
patternData: '{}',
cacheBuster: patternlab.cacheBuster,
}
)
.then((footerPartial) => {
const headFootData = patternlab.data;
headFootData.patternLabFoot = footerPartial;
return render(patternlab.userFoot, headFootData);
})
.catch((reason) => {
console.log(reason);
logger.error('error during footer render()');
});
return Promise.all([headerPromise, footerPromise]).then(
(headFootPromiseResults) => {
// build the viewall pages
return buildViewAllPages(
headFootPromiseResults[0],
patternlab,
styleguidePatterns,
uikit
)
.then((allPatterns) => {
// todo track down why we need to make this unique in the first place
const uniquePatterns = uniqueAllPatterns(
allPatterns,
patternlab
);
// add the defaultPattern if we found one
if (patternlab.defaultPattern) {
uniquePatterns.push(patternlab.defaultPattern);
addToPatternPaths(patternlab, patternlab.defaultPattern);
}
// build the main styleguide page
return render(
Pattern.createEmpty(
{
extendedTemplate: uikit.viewAll,
},
patternlab
),
{
partials: uniquePatterns,
},
{
patternSection: uikit.patternSection,
patternSectionSubgroup: uikit.patternSectionSubgroup,
}
)
.then((styleguideHtml) => {
fs.outputFileSync(
path.resolve(
path.join(
process.cwd(),
uikit.outputDir,
paths.public.styleguide,
'html/styleguide.html'
)
),
headFootPromiseResults[0] +
styleguideHtml +
headFootPromiseResults[1]
);
logger.info('Built Pattern Lab front end');
// move the index file from its asset location into public root
let patternlabSiteHtml;
try {
patternlabSiteHtml = fs.readFileSync(
path.resolve(
path.join(
uikit.modulePath,
paths.source.styleguide,
'index.html'
)
),
'utf8'
);
} catch (err) {
logger.error(
`Could not load one or more styleguidekit assets from ${paths.source.styleguide}`
);
}
fs.outputFileSync(
path.resolve(
path.join(
process.cwd(),
uikit.outputDir,
paths.public.root,
'index.html'
)
),
patternlabSiteHtml
);
//write out patternlab.data object to be read by the client
exportData(patternlab, uikit);
resolve();
})
.catch((reason) => {
console.log(reason);
logger.error('error during buildFrontend()');
});
})
.catch((reason) => {
console.log(reason);
logger.error('error during buildViewAllPages()');
});
}
);
});
});
return Promise.all(uikitPromises);
}
return {
buildFrontend: buildFrontend,
isPatternExcluded: isPatternExcluded,
groupPatterns: groupPatterns,
resetUIBuilderState: resetUIBuilderState,
uniqueAllPatterns: uniqueAllPatterns,
buildViewAllPages: buildViewAllPages,
};
};
module.exports = ui_builder;