Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Lists fonts used within a Mapbox account, which fonts each Style is using, and which Styles are using each font. Useful for knowing which fonts you can clear out of your account to keep under the 100 fonts limit.
#!/usr/bin/env node
/* eslint-disable */
const MapboxClient = require('.');
const MapboxStyles = require('./services/styles');
const MapboxFonts = require('./services/fonts');
const fs = require('fs');
const fontsService = MapboxFonts({ accessToken: process.env.MAPBOX_ACCESS_TOKEN });
const stylesService = MapboxStyles({ accessToken: process.env.MAPBOX_ACCESS_TOKEN });
fontsService.listFonts({ownerId: 'mapbox'})
.send()
.then(response => {
const mapboxFonts = response.body
fontsService.listFonts({fresh: true})
.send()
.then(response => {
const fonts = response.body
fs.writeFileSync('fonts.json', JSON.stringify(fonts, null, 2))
console.log('fonts.json')
listStyles(stylesService, (err, stylesList) => {
fs.writeFileSync('stylesList.json', JSON.stringify(stylesList, null, 2))
console.log('stylesList.json')
const fetchStyles = stylesList.map(style => {
return new Promise((resolve, reject) => {
stylesService.getStyle({
styleId: style.id,
fresh: true
})
.send()
.then(response => {
resolve(response.body)
}, error => {
console.error(error)
reject(error)
})
})
})
Promise.all(fetchStyles)
.then(styles => {
const fontsPerStyle = styles.map(style => {
const fontsUsed = style.layers.map(layer => {
if (layer.layout && layer.layout['text-font']) {
const textFont = layer.layout['text-font']
if (Array.isArray(textFont)) {
if (textFont[0] === 'step') {
return textFont.map(v => {
if (v && Array.isArray(v) && v[0] === 'literal') {
return v[1]
} else {
return []
}
}).flat()
} else {
return textFont
}
return textFont
} else if (typeof textFont === 'object') {
if (textFont.stops) {
return textFont.stops.map(stop => {
return stop[1]
}).flat()
} else {
console.error('Unknown text-font value', textFont)
}
} else {
return [textFont]
}
} else {
return []
}
}).flat()
const uniqueFontsUsed = [...new Set(fontsUsed)].sort()
return {
styleId: style.id,
styleName: style.name,
fonts: uniqueFontsUsed
}
})
fs.writeFileSync('fontsPerStyle.json', JSON.stringify(fontsPerStyle, null, 2))
console.log('fontsPerStyle.json')
// find which styles this font is used in
const stylesPerFont = {}
fonts.map(font => {
stylesPerFont[font] = []
})
// fonts found in styles but not found in the account
const styleFontsMissingInAccount = {}
fontsPerStyle.map(styleFonts => {
styleFonts.fonts.map(font => {
const style ={
styleId: styleFonts.styleId,
styleName: styleFonts.styleName
}
if (font in stylesPerFont) {
stylesPerFont[font].push(style)
} else {
// the font ways not found in our account fonts, but also check to see if it is a Mapbox font
if (!mapboxFonts.includes(font)) {
if (!(font in styleFontsMissingInAccount)) {
styleFontsMissingInAccount[font] = []
}
styleFontsMissingInAccount[font].push(style)
}
}
})
})
fs.writeFileSync('stylesPerFont.json', JSON.stringify(stylesPerFont, null, 2))
console.log('fontsPerStyle.json')
fs.writeFileSync('styleFontsMissingInAccount.json', JSON.stringify(styleFontsMissingInAccount, null, 2))
console.log('styleFontsMissingInAccount.json')
})
}, error => {
console.error(error.message);
});
}, error => {
console.error(error.message)
})
}, error => {
console.error(error.message)
})
/**
* Retrieve the styles and return them as an Array
*/
function listStyles(stylesService, cb) {
process.stdout.write('Styles List');
const styles = [];
stylesService.listStyles({
fresh: true
}).eachPage((err, res, next) => {
process.stdout.write('.');
if (err) {
console.error(err);
cb(err, null);
return;
}
const pageStyles = res.body;
styles.push(...pageStyles);
if (!res.hasNextPage()) {
// no more pages
console.log(`Fetched ${styles.length} styles`);
cb(null, styles);
} else {
// call the next page
next();
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment