@uiengine/core
Version:
Create, document and evolve your design system collaboratively.
112 lines (94 loc) • 3.67 kB
JavaScript
const R = require('ramda')
const {
UiengineInputError,
StringUtil: { hasContent },
PageUtil: { isDocumentationPage, isIndexPage, pageIdForComponentId, pageIdToPath, pagePathForComponentId, parentIdForPageId }
} = require('@uiengine/util')
const assocNavigation = (navigation, entry) =>
R.assoc(entry.id, entry, navigation)
const dataForPageId = (state, id) => {
const { pages, components } = state
// page
const page = pages[id]
const availableComponentIds = components ? Object.keys(components) : []
const componentIds = page.componentIds || []
const componentPageIds = R.map(componentId => {
if (availableComponentIds.includes(componentId)) {
return pageIdForComponentId(id, componentId)
} else {
throw new UiengineInputError([
`Component "${componentId}" does not exist, but was inserted on page "${id}".`,
'Here is a list of available components:',
availableComponentIds.map(id => `- ${id}`).join('\n')
])
}
}, componentIds)
const childIds = page.childIds.concat(componentPageIds)
const relations = dataForRelations(pages, id, childIds)
const data = R.mergeRight(relations, {
id,
itemId: id,
isStructural: isDocumentationPage(page.type) && !hasContent(page.content),
path: isIndexPage(id) ? '/' : `/${page.path}/`,
type: page.type,
title: page.title,
keywords: (page.keywords || []).concat(page.tags || [])
})
if (!data.isStructural) delete data.isStructural
if (page.collapsed) data.collapsed = true
if (data.keywords.length === 0) delete data.keywords
// component childpages
const componentData = R.partial(dataForComponentId, [state, page])
const componentsData = R.map(componentData, componentIds)
return [data, ...componentsData]
}
const dataForComponentId = (state, parent, id) => {
const { components, pages } = state
const component = components[id]
const pageId = pageIdForComponentId(parent.id, component.id)
const pagePath = pagePathForComponentId(parent.path, component.id)
const relations = dataForRelations(pages, pageId, [])
const variantTags = R.uniq(R.flatten(R.pluck('tags', component.variants)))
const data = R.mergeRight(relations, {
id: pageId,
itemId: id,
path: `/${pagePath}/`,
type: component.type,
title: component.title,
keywords: (component.keywords || []).concat(component.tags || []).concat(variantTags)
})
if (data.keywords.length === 0) delete data.keywords
return data
}
const dataForRelations = (pages, id, childIds) => {
let siblings = []
const data = {}
const pageIds = Object.keys(pages)
const parentId = parentIdForPageId(pageIds, id)
const parent = pages[parentId]
if (parent) {
const parentPrefix = pageIdToPath(parent.id)
const parentComponentPageIds = R.map(componentId => `${parentPrefix}/${componentId}`, parent.componentIds || [])
siblings = (parent.childIds || []).concat(parentComponentPageIds)
}
const indexInSiblings = R.indexOf(id, siblings)
if (indexInSiblings > 0) data.prevSiblingId = siblings[indexInSiblings - 1]
if (indexInSiblings < siblings.length - 1) data.nextSiblingId = siblings[indexInSiblings + 1]
if (childIds.length) data.childIds = childIds
if (parentId) data.parentId = parentId
return data
}
async function fetch (state) {
const ids = Object.keys(state.pages)
const data = R.partial(dataForPageId, [state])
const navigationData = R.chain(data, ids)
const navigation = R.reduce(assocNavigation, {}, navigationData)
return navigation
}
async function fetchForPageId (state, id) {
return dataForPageId(state, id)
}
module.exports = {
fetch,
fetchForPageId
}