UNPKG

patternplate-server

Version:

Programmatically serve atomic patterns via a REST API

161 lines (127 loc) 4.47 kB
import {merge, uniqBy} from 'lodash'; import getPatternRetriever from './utilities/get-pattern-retriever'; import getPatternSource from './get-pattern-source'; import getComponent from './get-component'; import layout from '../application/layouts'; export default getPatternDemo; async function getPatternDemo(application, id, filters, environment) { const getFile = getPatternSource(application); filters.outFormats = ['html']; const [pattern] = await getPatternRetriever(application)(id, filters, environment, ['read']); if (!pattern) { return null; } const order = ['demo', 'index']; const path = Object.values(pattern.files) .sort((a, b) => order.indexOf(a.basename) - order.indexOf(b.basename)) .map(file => file.path)[0]; if (!path) { return null; } const content = await getFile(path, 'transformed', environment); const {formats} = application.configuration.patterns; const automount = selectAutoMount(application, pattern); if (automount) { await getComponent(application, pattern.id, environment); } const render = getRenderer(formats, automount); const resources = (application.resources || []).filter(({pattern: p}) => p === null || p === pattern.id); return render(content.body, pattern, resources); } function selectAutoMount(a, p) { const transform = a.configuration.transforms['react-to-markup'] || {}; const pattern = selectReactToMarkup(selectManifestOptions(p)); const settings = merge({}, transform.opts, pattern.opts); return settings.automount || false; } function selectReactToMarkup(o) { return o['react-to-markup'] || {}; } function selectManifestOptions(p) { return p.manifest.options || {}; } function getRenderer(formats, component = false) { return (content, result, resources) => { const transforms = result.config.transforms; const styleFormat = getFormat(formats, transforms, 'style'); const scriptFormat = getFormat(formats, transforms, 'script'); const styleReference = getUriByFormat(result, styleFormat); const markupContent = [{content}]; const styleContent = resources.filter(r => r.type === 'css' && !r.reference); const scriptContent = resources.filter(r => r.type === 'js' && !r.reference); const scripts = component ? [] : [{uri: getUriByFormat(result, scriptFormat)}]; const styles = [{id: styleReference}].filter(i => i.id); const markupReferences = uniqBy(resources.filter(r => r.type === 'html' && r.reference), 'id'); const styleReferences = uniqBy([...styles, ...resources.filter(r => r.type === 'css' && r.reference)], 'id'); const scriptReferences = uniqBy([...resources.filter(r => r.type === 'js' && r.reference), ...scripts], 'id'); return layout({ title: result.id, content: { markup: markupContent, style: styleContent, script: scriptContent }, reference: { markup: markupReferences, style: styleReferences, script: scriptReferences } }); }; } const formatNames = { markup: 'html', style: 'css', script: 'js' }; function getUriByFormat(pattern, format = '') { if (!format) { return null; } const outFormats = pattern.outFormats || []; const type = format.toLowerCase(); const match = outFormats.find(o => o.type === type); if (match) { return `./index.${match.extension}`; } return null; } function getFormat(formats, transforms, type) { const entries = Object.entries(formats); // try to get a format with matching outFormat // markup => html // style => css // script => js const formatName = formatNames[type]; const found = entries.find(findByOutFormat(formatName, transforms)); if (found) { return (found[1] || {}).name || found[0]; } // Legacy get format by name // {name: 'Format'} const legacy = entries.find(findByName(type)); if (legacy) { return (legacy[0] || {}).name || legacy[0]; } return null; } function findByName(name) { return entry => entry[1].name.toLowerCase() === name; } function findByOutFormat(name, transforms) { return entry => { const outFormat = getOutFormat(entry, transforms); return name === outFormat; }; } function getOutFormat(entry, transforms) { const entryTransforms = entry[1].transforms || []; // If no transforms are configured // use the inbound transform extension as outFormat if (!entryTransforms.length) { return entry[0]; } const transformName = entryTransforms[entryTransforms.length - 1]; const transformConfig = transforms[transformName]; return transformConfig.outFormat; }