UNPKG

@agency-undone/nuxt-module-ecosystem-directory

Version:

A Nuxt module that loads all the boilerplate layouts, pages, components, styles, stores and functionality to run the Ecosystem Directory.

235 lines (224 loc) 9.04 kB
// ///////////////////////////////////////////////////////// Imports & Variables // ----------------------------------------------------------------------------- const Fs = require('fs-extra') const Sass = require('sass') const paths = { prefixed: false, // key to ensure path prefixing only happens once during compile projects: `content/projects`, staticDir: `static`, taxonomies: `static/content/core_taxonomy.json`, settings: `static/content/core_settings.json`, project_routes: `static/content/project-routes.json`, project_list: `static/content/project-list.json`, showcase_data: `static/content/showcase-data.json` } // /////////////////////////////////////////////////////////////////// Functions // ----------------------------------------------------------------------------- /* Prefix paths with the application root directory */ const prefixPaths = (instance) => { const appRootDir = instance.options.rootDir return new Promise((next) => { if (!paths.prefixed) { Object.keys(paths).map((key) => { paths[key] = `${appRootDir}/${paths[key]}` }) paths.prefixed = true } next() }) } /* Grab the project list and generate an array of slugs based on project filenames */ const getSlugs = async () => { try { const slugs = await Fs.readdirSync(paths.projects) .filter(obj => obj !== '.DS_Store') .map(obj => obj.split('.')[0]) console.log(slugs.join('\n')) return slugs } catch (e) { console.log('============================================ [getSlugs] Error') throw e } } /* Convert taxonomies file to a different Object structure → for showcase-data.json */ const reformatTaxonomies = async (taxonomies) => { try { const compiled = {} taxonomies.categories.forEach((category) => { const tags = {} category.tags.forEach((tag) => { tags[tag.slug] = tag.label }) compiled[category.slug] = { label: category.label, tags } }) return compiled } catch (e) { console.log('============================= [reformatTaxonomies] Error') throw e } } /* Convert taxonomies file to a different Object structure → for static/embeddable-view.js */ const generateTaxonomyListFile = async (slug, activeFilters) => { try { const taxonomies = JSON.parse(await Fs.readFileSync(paths.taxonomies)) const category = taxonomies.categories.filter(category => category.slug === slug) const tags = category.length && category[0] ? category[0].tags : [] const len = tags.length const compiled = [] for (let i = 0; i < len; i++) { if (activeFilters.indexOf(tags[i].slug) > -1) { compiled.push({ label: tags[i].label, value: tags[i].slug }) } } return compiled } catch (e) { console.log('============================ [generateTaxonomyListFile] Error') throw e } } /* Match taxonomy schema with project taxonomy → for showcase-data.json */ const compileTags = (project, categories, tags) => { return new Promise((next, reject) => { project.taxonomies.forEach((taxonomy) => { const category = categories.filter(category => category.slug === taxonomy.slug) if (category.length === 0 || !category[0].tags) { return } tags[taxonomy.slug] = taxonomy.tags.filter( tag => category[0].tags.map(t => t.slug).includes(tag) ) }) next() }) } /* - Open and parse all project JSON files - Push all of them into an array (to be used by main app and nuxt.config.js routes/generate block) - Push all of them into an array with some information removed (to be used by embedable-view.js and the showcase view) */ const generateProjectManifestFiles = async (slugs, primaryCategory, taxonomies) => { try { const len = slugs.length if (len === 0) { throw new Error('[manifestor.js] Unable to generate Project files because no projects exist') } const payload = { full: [], mini: [], activeFilters: [], showcase: { taxonomies: await reformatTaxonomies(taxonomies), projects: [] }, routes: [] } for (let i = 0; i < len; i++) { const slug = slugs[i] const project = JSON.parse(await Fs.readFileSync(`${paths.projects}/${slug}.json`)) const filterItems = project.taxonomies.filter(taxonomy => taxonomy.slug === primaryCategory) const filters = filterItems.length && filterItems[0].tags ? filterItems[0].tags : [] const tags = {} await compileTags(project, taxonomies.categories, tags) project.slug = slug payload.full.push(project) payload.mini.push({ slug, name: project.name, logo: project.logo, description: project.description, org: project.org, featured: project.featured, sortNumbers: project.sortNumbers, filters }) filters.forEach(filter => { if (payload.activeFilters.indexOf(filter) < 0) { payload.activeFilters.push(filter) } }) payload.showcase.projects.push({ name: project.name, logo: project.logo.icon || project.logo.full, tags }) payload.routes.push({ route: `/project/${slug}`, payload: project }) } return payload } catch (e) { console.log('======================== [generateProjectManifestFiles] Error') throw e } } /* Generate Embeddable View File */ const generateEmbeddableViewFile = async (projectList, activeFilters, primaryCategory, slugs, settings) => { try { settings = settings.embeddable_view const taxonomyList = await generateTaxonomyListFile(primaryCategory, activeFilters) const compiledCSS = Sass.renderSync({ file: `${__dirname}/../assets/scss/embeddable-view.scss`, outputStyle: 'compressed' }).css const vueJS = await Fs.readFileSync(`${__dirname}/../assets/js/vue.2.6.14.min.js`, 'utf8') let embeddableView = await Fs.readFileSync(`${__dirname}/../assets/js/embeddable-view.js`, 'utf8') // Inject content embeddableView = embeddableView.replace('INJECT_PROJECTS_LIST', JSON.stringify(projectList)) embeddableView = embeddableView.replace('INJECT_FILTERS', JSON.stringify(taxonomyList)) embeddableView = embeddableView.replace('INJECT_PROJECTS_STYLES', compiledCSS) embeddableView = embeddableView.replace('INJECT_VUE_SCRIPT', vueJS) // Inject settings embeddableView = embeddableView.replace(/INJECT_SETTINGS_HOST/g, settings.host) embeddableView = embeddableView.replace(/INJECT_SETTINGS_TARGET/g, settings.target) embeddableView = embeddableView.replace(/INJECT_SETTINGS_HEADING/g, settings.copy.heading) embeddableView = embeddableView.replace(/INJECT_SETTINGS_SUBHEADING/g, settings.copy.subheading) embeddableView = embeddableView.replace(/INJECT_SETTINGS_PROJECT_LINK/g, settings.copy.project_link) embeddableView = embeddableView.replace(/INJECT_SETTINGS_ECOSYSTEM_LINK/g, settings.copy.ecosystem_link) embeddableView = embeddableView.replace(/INJECT_SETTINGS_FILTER_ALL/g, settings.copy.filter_all) embeddableView = embeddableView.replace(/INJECT_SETTINGS_SORT_A_Z/g, settings.copy.sort_a_z) embeddableView = embeddableView.replace(/INJECT_SETTINGS_SORT_Z_A/g, settings.copy.sort_z_a) embeddableView = embeddableView.replace(/INJECT_SETTINGS_SORT_DATE_ASC/g, settings.copy.sort_date_asc) embeddableView = embeddableView.replace(/INJECT_SETTINGS_SORT_DATE_DESC/g, settings.copy.sort_date_desc) return embeddableView } catch (e) { console.log('========================== [generateEmbeddableViewFile] Error') throw e } } // ////////////////////////////////////////////////////////////////// Manifestor // ----------------------------------------------------------------------------- const Manifestor = async (instance) => { try { console.log('🚀️ Manifest projects started') await prefixPaths(instance) const slugs = await getSlugs() const settings = JSON.parse(Fs.readFileSync(paths.settings)) const taxonomies = JSON.parse(await Fs.readFileSync(paths.taxonomies)) const primaryCategory = settings.behavior.primaryCategorySlug const payload = await generateProjectManifestFiles(slugs, primaryCategory, taxonomies) await Fs.writeFileSync(paths.project_routes, JSON.stringify(payload.routes)) await Fs.writeFileSync(paths.project_list, JSON.stringify(payload.full)) await Fs.writeFileSync(paths.showcase_data, JSON.stringify(payload.showcase)) if (settings.visibility.embeddableObject) { const embeddableViewScript = await generateEmbeddableViewFile(payload.mini, payload.activeFilters, primaryCategory, slugs, settings) await Fs.writeFileSync(`${paths.staticDir}/embeddable-view.js`, embeddableViewScript) } console.log('🏁 Manifest projects complete') } catch (e) { console.log('========================================== [Manifestor] Error') console.log(e) } } export default Manifestor