Color Resolution
applyTint
function
Apply a tint to a concrete ARGB colour: convert to HLS, shift the luminance, convert back.
The shift is ECMA-376's (§18.3.1.15): -1 darkens to black, +1 lightens to white, 0 is a no-op. The spec states the formula but not the rounding either side of the RGB↔HLS conversion, so an implementation cannot be checked against the prose alone. This one lands within 2/255 per channel of what Excel Desktop itself renders, measured over three hues × twelve tints and recorded in test/corpus/fixtures/excel-oracle/theme-color-tint-luminance.json. Closing that last gap would mean reproducing one Excel build's fixed-point HLS rounding, and the difference is not visible.
function applyTint(argb: string, tint: number): string;ColorResolutionContext
interface
What a colour reference is resolved against: the workbook's theme scheme and indexed palette.
interface ColorResolutionContext {
/** The theme's colour scheme; the Office default when the workbook carries no theme of its own. */
readonly theme?: ThemeColorScheme | undefined;
/**
* The workbook's custom indexed palette, by index, each entry an ARGB string. Empty or absent means
* the workbook rides {@link DEFAULT_INDEXED_COLORS}. A custom palette replaces the built-in one
* wholesale, which is what `<indexedColors>` means, so a short custom palette leaves the indices
* past its end unresolved rather than falling through to the built-in entry.
*/
readonly indexed?: readonly string[] | undefined;
}DEFAULT_INDEXED_COLORS
const
The built-in indexed colour palette (ECMA-376 §18.8.27), by index. Entries 0–7 duplicate 8–15, a redundancy the spec preserves for backwards compatibility with the legacy formats this palette came from, and the table is only 64 long: indices 64 and 65 are the system foreground and background, which name whatever the operating system's window colours are and therefore have no fixed value at all (see SYSTEM_INDEXED_COLORS).
The spec writes each entry with a leading 00. That byte is not an alpha channel, since a palette of fully transparent colours would be absurd. It is an artefact of the 32-bit colour records these values were lifted from, which is why resolveColor returns them fully opaque.
const DEFAULT_INDEXED_COLORS: readonly string[]resolveColor
function
Resolve a colour reference to a concrete 8-hex ARGB string, or undefined when it cannot be resolved: an auto colour, a system indexed colour, a theme slot the workbook's scheme does not declare, or an index past the end of a custom palette.
Precedence follows what the encodings mean: an explicit argb is already concrete and wins; then theme, then indexed. A tint applies to whatever the base resolved to.
Alpha: a resolved theme/indexed colour comes back fully opaque, because neither the theme scheme nor the palette carries a meaningful alpha (see DEFAULT_INDEXED_COLORS). An explicit argb keeps the alpha the file stated.
function resolveColor(
color: Color,
context: ColorResolutionContext = {},
): string | undefined;SYSTEM_INDEXED_COLORS
const
The two indices that are not colours: 64 is the system foreground and 65 the system background. They resolve to whatever the viewing system's window colours are, so this library reports them unresolved rather than inventing black and white: a caller that wants to paint them must decide for itself what "automatic" means in its context. indexed="64" in particular is extremely common: it is the placeholder every solid fill Excel writes carries as its background colour.
const SYSTEM_INDEXED_COLORS: ReadonlySet<number>