While it was kind of nice having everything at the top level, the number of files is now getting a bit unwieldy and hard to understand, so I took a stab at organizing the directories without introducing too much nesting. Test Plan: - Ran `npm run serve` to ensure that local builds still work - Ran `npm run prepack` then `open dist/release/index.html` to ensure that release builds still work - Ran `scripts/deploy.sh` to ensure that the deployed version of the site will still work when I eventually redeploy - Ran `npm run jest` to ensure that tests still work correctly
40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
import {binarySearch} from './utils'
|
|
|
|
export const ELLIPSIS = '\u2026'
|
|
|
|
// NOTE: This blindly assumes the same result across contexts.
|
|
const measureTextCache = new Map<string, number>()
|
|
|
|
let lastDevicePixelRatio = -1
|
|
export function cachedMeasureTextWidth(ctx: CanvasRenderingContext2D, text: string): number {
|
|
if (window.devicePixelRatio !== lastDevicePixelRatio) {
|
|
// This cache is no longer valid!
|
|
measureTextCache.clear()
|
|
lastDevicePixelRatio = window.devicePixelRatio
|
|
}
|
|
if (!measureTextCache.has(text)) {
|
|
measureTextCache.set(text, ctx.measureText(text).width)
|
|
}
|
|
return measureTextCache.get(text)!
|
|
}
|
|
|
|
function buildTrimmedText(text: string, length: number) {
|
|
const prefixLength = Math.floor(length / 2)
|
|
const prefix = text.substr(0, prefixLength)
|
|
const suffix = text.substr(text.length - prefixLength, prefixLength)
|
|
return prefix + ELLIPSIS + suffix
|
|
}
|
|
|
|
export function trimTextMid(ctx: CanvasRenderingContext2D, text: string, maxWidth: number) {
|
|
if (cachedMeasureTextWidth(ctx, text) <= maxWidth) return text
|
|
const [lo] = binarySearch(
|
|
0,
|
|
text.length,
|
|
n => {
|
|
return cachedMeasureTextWidth(ctx, buildTrimmedText(text, n))
|
|
},
|
|
maxWidth,
|
|
)
|
|
return buildTrimmedText(text, lo)
|
|
}
|