Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 1x 1x 1x 1x 1x 4x 4x 4x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import * as glob from "glob" import * as path from "path" import * as lodash from "lodash" import { BAKED_BASE_URL, OPTIMIZE_SVG_EXPORTS, BAKED_SITE_DIR, } from "../settings/serverSettings" import * as db from "../db/db" import { bakeGraphersToSvgs } from "../baker/GrapherImageBaker" import { warn } from "../serverUtils/slackLog" import { Chart } from "../db/model/Chart" import md5 from "md5" import { Url } from "../clientUtils/urls/Url" interface ChartExportMeta { key: string svgUrl: string version: number width: number height: number } // Splits a grapher URL like https://ourworldindata.org/grapher/soil-lifespans?tab=chart // into its slug (soil-lifespans) and queryStr (?tab=chart) export const grapherUrlToSlugAndQueryStr = (grapherUrl: string) => { const url = Url.fromURL(grapherUrl) const slug = lodash.last(url.pathname?.split("/")) as string const queryStr = url.queryStr return { slug, queryStr } } // Combines a grapher slug, and potentially its query string, to _part_ of an export file // name. It's called fileKey and not fileName because the actual export filename also includes // other parts, like chart version and width/height. export const grapherSlugToExportFileKey = ( slug: string, queryStr: string | undefined ) => `${slug}${queryStr ? `-${md5(queryStr)}` : ""}` export interface GrapherExports { get: (grapherUrl: string) => ChartExportMeta | undefined } export const bakeGrapherUrls = async (urls: string[]) => { const currentExports = await getGrapherExportsByUrl() const slugToId = await Chart.mapSlugsToIds() const toBake = [] // Check that we need to bake this url, and don't already have an export for (const url of urls) { const current = currentExports.get(url) if (!current) { toBake.push(url) continue } const slug = lodash.last(Url.fromURL(url).pathname?.split("/")) if (!slug) { warn(`Invalid chart url ${url}`) continue } const chartId = slugToId[slug] if (chartId === undefined) { warn(`Couldn't find chart with slug ${slug}`) continue } const rows = await db.queryMysql( `SELECT charts.config->>"$.version" AS version FROM charts WHERE charts.id=?`, [chartId] ) if (!rows.length) { warn(`Mysteriously missing chart by id ${chartId}`) continue } if (rows[0].version > current.version) toBake.push(url) } if (toBake.length > 0) { for (const grapherUrls of lodash.chunk(toBake, 5)) { await bakeGraphersToSvgs( grapherUrls, `${BAKED_SITE_DIR}/exports`, OPTIMIZE_SVG_EXPORTS ) } } } export const getGrapherExportsByUrl = async (): Promise<GrapherExports> => { // Index the files to see what we have available, using the most recent version // if multiple exports exist const files = glob.sync(`${BAKED_SITE_DIR}/exports/*.svg`) const exportsByKey = new Map<string, ChartExportMeta>() for (const filepath of files) { const filename = path.basename(filepath) const [key, version, dims] = filename.toLowerCase().split("_") const versionNumber = parseInt(version.split("v")[1]) const [width, height] = dims.split("x") const current = exportsByKey.get(key) if (!current || current.version < versionNumber) { exportsByKey.set(key, { key: key, svgUrl: `${BAKED_BASE_URL}/exports/${filename}`, version: versionNumber, width: parseInt(width), height: parseInt(height), }) } } return { get(grapherUrl: string) { const { slug, queryStr } = grapherUrlToSlugAndQueryStr(grapherUrl) return exportsByKey.get( grapherSlugToExportFileKey(slug, queryStr).toLowerCase() ) }, } } |