Skip to content

Instantly share code, notes, and snippets.

@mattmccray
Created August 12, 2020 19:43
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save mattmccray/da825d7bdc3bb8b775cf540f3c58fc14 to your computer and use it in GitHub Desktop.
Tilt taxonomy class
import _ from 'lodash'
class TagSet {
constructor({ name, slug, sortBy = 'title' }) {
/** @type {string} */
this.name = name
/** @type {string} */
this.slug = slug
/** @type {string} */
this.sortBy = sortBy
/** @type {Page[]} */
this.pages = []
/** @type {Map.<string, TagSet>} */
this.nested = new Map()
}
toJSON() {
return {
name: this.name,
slug: this.slug,
pages: _.sortBy(this.pages, this.sortBy),
}
}
}
export class Taxonomy {
constructor(files, hiddenField = 'hideInSiteMap') {
this.cataloguedPages = []
/** @type {Map.<string, TagSet>} */
this.tags = new Map()
/** @type {Map.<string, TagSet>} */
this.categories = new Map()
/** @private */this._hiddenField = hiddenField
this._generateIndex(files)
}
get tagList() {
return _.sortBy(Array.from(this.tags.values()).map(tagset => tagset.toJSON()), 'pages.length').reverse()
}
get categoryList() {
return this._categoryMapToArray(this.categories)
}
/**
* @param {string} category Nested category names look like: "Books/Classic"
* @param {boolean} [includeNested] (Not used yet)
*/
getPagesForCategory(category, includeNested = false) {
let parts = category.trim().split('/')
/** @type {TagSet} */
let catMap
let cat = this.categories
while (parts.length > 0) {
const part = parts.shift()
catMap = cat.get(part)
cat = catMap.nested
}
return catMap.pages
}
/**
* @param {string} tagName Use tag.name as the key
*/
getPagesForTagName(tagName) {
if (this.tags.has(tagName)) return this.tags.get(tagName).pages
else return []
}
/** @private */
_categoryMapToArray(catMap, sortField = 'title') {
if (!catMap) return null
return _.sortBy(Array.from(catMap.values()).map(tagset => ({
name: tagset.name,
slug: tagset.slug,
pages: _.sortBy(tagset.pages, sortField),
nested: this._categoryMapToArray(tagset.nested)
})), 'name')
}
/** @private */
_generateIndex(files) {
Object.keys(files).forEach(filename => {
const page = files[filename]
if (page[this._hiddenField] == true) return
const hasTags = ('tags' in page)
const hasCategories = ('categories' in page)
if (hasTags) {
page.tags.forEach(tag => {
if (!this.tags.has(tag.name)) {
this.tags.set(tag.name, new TagSet(tag))
}
this.tags.get(tag.name).pages.push(page)
})
}
if (hasCategories) {
page.categories.forEach(category => {
let catMap = this.categories
/** @type {TagSet} */
let catSet = null
category.forEach(cat => {
if (!catMap.has(cat.name)) catMap.set(cat.name, new TagSet(cat))
catSet = catMap.get(cat.name)
catMap = catSet.nested
})
catSet.pages.push(page)
})
}
if (hasTags || hasCategories) {
this.cataloguedPages.push(page)
}
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment