Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 59 additions & 12 deletions src/patches/themes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import { Theme } from '../types';
import { LocationResult, showDiff } from './index';

function getThemesLocation(oldFile: string): {
type ThemesLocation = {
switchStatement: LocationResult;
objArr: LocationResult;
obj: LocationResult;
} | null {
objArr: LocationResult & { isAssemblyPrefix?: boolean };
obj: LocationResult & { prefix: string };
};

function getThemesLocation(oldFile: string): ThemesLocation | null {
// === Switch Statement ===
// CC >=2.1.83: switch(A){case"light":return LX9;...default:return CX9}
// CC <2.1.83: switch(A){case"light":return{...};...}
Expand Down Expand Up @@ -70,7 +72,9 @@ function getThemesLocation(oldFile: string): {
}

// === Theme Options Array ===
// Both old and new: [{label:"...",value:"..."}, ...] or [{"label":"...",...]
// Old format: [{label:"Dark mode",value:"dark"},{label:"Light mode",value:"light"},...]
// New format (CC >=2.1.92): HH=[{label:"Auto (match terminal)",value:"auto"}] only,
// with individual vars DH,YH,... spread in assembly: e=[...HH,DH,YH,...,...X.map(kB1),...FH]
const objArrPat =
/\[(?:\.\.\.\[\],)?(?:\{"?label"?:"(?:Dark|Light|Auto|Monochrome)[^"]*","?value"?:"[^"]+"\},?)+\]/;
const objArrMatch = oldFile.match(objArrPat);
Expand All @@ -80,8 +84,41 @@ function getThemesLocation(oldFile: string): {
return null;
}

// Check if new assembly format: objArr has only 1 item (just "auto" option)
let objArrLocation: LocationResult & { isAssemblyPrefix?: boolean } = {
startIndex: objArrMatch.index,
endIndex: objArrMatch.index + objArrMatch[0].length,
};
const objArrItemCount = (objArrMatch[0].match(/"?value"?:/g) || []).length;
if (objArrItemCount === 1) {
// Find the variable name holding this single-item array (e.g. "HH")
const beforeObjArr = oldFile.slice(
Math.max(0, objArrMatch.index - 30),
objArrMatch.index
);
const varNameMatch = beforeObjArr.match(/([A-Za-z_$][\w$]*)=$/);
if (varNameMatch) {
const autoVarName = varNameMatch[1].replace(/[$]/g, '\\$');
// Find assembly: [...autoVar, theme1, theme2, ..., ...customThemes.map(
const assemblyPat = new RegExp(
`\\[\\.\\.\\.${autoVarName}(?:,[A-Za-z_$][\\w$]*){2,},\\.\\.\\.`
);
const assemblyMatch = oldFile.match(assemblyPat);
if (assemblyMatch && assemblyMatch.index != undefined) {
// assemblyMatch[0] ends with ",..." — endIndex is right before "..."
// Replacement "[{theme},..." joins cleanly with remaining "...X.map(kB1),...FH]"
objArrLocation = {
startIndex: assemblyMatch.index,
endIndex: assemblyMatch.index + assemblyMatch[0].length - 3,
isAssemblyPrefix: true,
};
}
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// === Theme Name Mapping Object ===
// {dark:"Dark mode",...} or {"dark":"Dark mode",...}
// Old: return{dark:"Dark mode",...}
// New (CC >=2.1.92): VAR={auto:"Auto...",dark:"Dark mode",...}
const objPat =
/(?:return|[$\w]+=)\{(?:"?(?:[$\w-]+)"?:"(?:Auto |Dark|Light|Monochrome)[^"]*",?)+\}/;
const objMatch = oldFile.match(objPat);
Expand All @@ -91,19 +128,20 @@ function getThemesLocation(oldFile: string): {
return null;
}

// Preserve the original prefix (either "return" or "VARNAME=")
const objPrefix = objMatch[0].slice(0, objMatch[0].indexOf('{'));

return {
switchStatement: {
startIndex: switchStart,
endIndex: switchEnd,
identifiers: [switchIdent],
},
objArr: {
startIndex: objArrMatch.index,
endIndex: objArrMatch.index + objArrMatch[0].length,
},
objArr: objArrLocation,
obj: {
startIndex: objMatch.index,
endIndex: objMatch.index + objMatch[0].length,
prefix: objPrefix,
},
};
}
Expand All @@ -126,8 +164,10 @@ export const writeThemes = (
// Process in reverse order to avoid index shifting

// Update theme mapping object (obj)
// Preserve the original prefix ("return" or "VARNAME=") to avoid turning a
// module-level variable assignment into an invalid return statement.
const obj =
'return' +
locations.obj.prefix +
JSON.stringify(
Object.fromEntries(themes.map(theme => [theme.id, theme.name]))
);
Expand All @@ -145,9 +185,16 @@ export const writeThemes = (
oldFile = newFile;

// Update theme options array (objArr)
const objArr = JSON.stringify(
// In new assembly format (CC >=2.1.92), objArr points to the prefix of the
// spread expression "[...auto,theme1,...,themeN," (endIndex is just before
// the custom-themes spread "...U.map(...)"). We emit an open array without
// the closing "]" so the existing suffix "...U.map(kB1),...FH]" completes it.
const themeItems = JSON.stringify(
themes.map(theme => ({ label: theme.name, value: theme.id }))
);
const objArr = locations.objArr.isAssemblyPrefix
? themeItems.slice(0, -1) + ',' // "[{...}," — no closing ], suffix provides it
: themeItems;
newFile =
newFile.slice(0, locations.objArr.startIndex) +
objArr +
Expand Down