@nonamelego/dsh-catppuccin 0.6.5-beta.0 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +149 -19
- package/lib/client.js.map +1 -1
- package/lib/index.js +938 -2
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -3449,6 +3449,46 @@ window.__ModuleLoader__.load({
|
|
|
3449
3449
|
}
|
|
3450
3450
|
];
|
|
3451
3451
|
//#endregion
|
|
3452
|
+
//#region src/boot-palette.ts
|
|
3453
|
+
/** Attribute marking the injected `<style>` so the Client can find it. */
|
|
3454
|
+
const BOOT_PALETTE_ATTR = "data-dsh-catppuccin-boot";
|
|
3455
|
+
//#endregion
|
|
3456
|
+
//#region src/client/boot-palette.ts
|
|
3457
|
+
/**
|
|
3458
|
+
* Client half of the pre-paint palette (issue #30 补充, 2026-10-27).
|
|
3459
|
+
*
|
|
3460
|
+
* The Host injects a `<style data-dsh-catppuccin-boot>` into the index HTML so
|
|
3461
|
+
* the first frame is already the persisted flavour (see `src/boot-palette.ts`).
|
|
3462
|
+
* That sheet is only a stand-in: its selector is `html body` (0,0,2), which
|
|
3463
|
+
* outranks the official `body` token block, so leaving it in place would pin
|
|
3464
|
+
* every token and defeat later theme switches (the user picks Light or turns the
|
|
3465
|
+
* flavour off and nothing changes).
|
|
3466
|
+
*
|
|
3467
|
+
* So it is removed the moment the flavour theme actually takes over — which is
|
|
3468
|
+
* NOT the same instant as "setTheme was called":
|
|
3469
|
+
* - a reload where the runtime preference already equals the flavour id never
|
|
3470
|
+
* calls setTheme (see `applyDesired`'s early return), and
|
|
3471
|
+
* - a built-in pick (Light / Dark / System) must remove it too, because the
|
|
3472
|
+
* sheet belongs to a flavour that is no longer wanted.
|
|
3473
|
+
* The restore effect therefore clears it from every one of those points plus a
|
|
3474
|
+
* fallback timer and the effect teardown.
|
|
3475
|
+
*/
|
|
3476
|
+
/**
|
|
3477
|
+
* Remove every injected pre-paint sheet from this document.
|
|
3478
|
+
*
|
|
3479
|
+
* Idempotent and safe when nothing was injected (hosts without the index
|
|
3480
|
+
* injection seam, `flavor: off`, a document that already cleared it).
|
|
3481
|
+
* @returns whether an element was actually removed (diagnostics and tests).
|
|
3482
|
+
*/
|
|
3483
|
+
function clearBootPalette() {
|
|
3484
|
+
let removed = false;
|
|
3485
|
+
for (const element of document.querySelectorAll(`[${BOOT_PALETTE_ATTR}]`)) {
|
|
3486
|
+
element.remove();
|
|
3487
|
+
removed = true;
|
|
3488
|
+
}
|
|
3489
|
+
return removed;
|
|
3490
|
+
}
|
|
3491
|
+
//#endregion
|
|
3452
3492
|
//#region src/client/shiki-tokens.ts
|
|
3453
3493
|
/**
|
|
3454
3494
|
* Canonical Catppuccin syntax colours per flavour.
|
|
@@ -4238,32 +4278,57 @@ window.__ModuleLoader__.load({
|
|
|
4238
4278
|
const reapplyThemePrefs = () => {
|
|
4239
4279
|
const active = theme.getTheme().preference;
|
|
4240
4280
|
const flavor = flavorInfo(active);
|
|
4241
|
-
if (flavor === void 0
|
|
4242
|
-
|
|
4281
|
+
if (flavor === void 0) return;
|
|
4282
|
+
const dispose = themeDisposers.get(flavor.themeId);
|
|
4283
|
+
if (dispose === void 0) return;
|
|
4284
|
+
themeDisposers.delete(flavor.themeId);
|
|
4285
|
+
dispose();
|
|
4243
4286
|
registerThemeFor(flavor);
|
|
4287
|
+
try {
|
|
4288
|
+
theme.setTheme(flavor.themeId);
|
|
4289
|
+
} catch {}
|
|
4244
4290
|
};
|
|
4245
4291
|
let lastWrittenSection;
|
|
4246
4292
|
let handleStaleConflict;
|
|
4293
|
+
let applyRestoredPreference;
|
|
4247
4294
|
let pendingLocalPush = false;
|
|
4295
|
+
let pendingLocalSection = null;
|
|
4296
|
+
let maxSeenRevision;
|
|
4297
|
+
let revisionKind;
|
|
4298
|
+
let lastDocumentSection = null;
|
|
4248
4299
|
let syncedSection = settingsSectionFromState(buildLocalState());
|
|
4249
4300
|
const baseRevisionTracker = createBaseRevisionTracker();
|
|
4250
4301
|
const queuePersist = () => {
|
|
4251
|
-
|
|
4302
|
+
const localSection = settingsSectionFromState(buildLocalState());
|
|
4303
|
+
if ((lastDocumentSection === null || !settingsSectionsEqual(localSection, lastDocumentSection)) && !settingsSectionsEqual(localSection, syncedSection)) {
|
|
4304
|
+
pendingLocalSection = localSection;
|
|
4305
|
+
if (!isScopeUsable(scope.getSnapshot())) pendingLocalPush = true;
|
|
4306
|
+
}
|
|
4252
4307
|
baseRevisionTracker.capture(() => scope.getSnapshot().revision);
|
|
4253
4308
|
scheduleDurablePersist(persistLocal);
|
|
4254
4309
|
};
|
|
4255
4310
|
const persistLocal = () => {
|
|
4256
4311
|
const baseRevision = baseRevisionTracker.take();
|
|
4257
|
-
if (!isScopeUsable(scope.getSnapshot()))
|
|
4312
|
+
if (!isScopeUsable(scope.getSnapshot())) {
|
|
4313
|
+
pendingLocalSection = null;
|
|
4314
|
+
return;
|
|
4315
|
+
}
|
|
4258
4316
|
const state = buildLocalState();
|
|
4317
|
+
const flushed = settingsSectionFromState(state);
|
|
4259
4318
|
persistStateToScope(scope, state, {
|
|
4260
4319
|
baseRevision,
|
|
4261
4320
|
lastWrittenSection
|
|
4262
4321
|
}).then((outcome) => {
|
|
4322
|
+
const settled = pendingLocalSection !== null && settingsSectionsEqual(pendingLocalSection, flushed);
|
|
4263
4323
|
if (outcome === "written") {
|
|
4264
|
-
lastWrittenSection =
|
|
4265
|
-
syncedSection =
|
|
4324
|
+
lastWrittenSection = flushed;
|
|
4325
|
+
syncedSection = flushed;
|
|
4326
|
+
if (settled) pendingLocalSection = null;
|
|
4327
|
+
} else if (outcome === "noop") {
|
|
4328
|
+
syncedSection = flushed;
|
|
4329
|
+
if (settled) pendingLocalSection = null;
|
|
4266
4330
|
} else if (outcome === "stale") {
|
|
4331
|
+
if (settled) pendingLocalSection = null;
|
|
4267
4332
|
emitConflict();
|
|
4268
4333
|
handleStaleConflict?.();
|
|
4269
4334
|
}
|
|
@@ -4271,28 +4336,49 @@ window.__ModuleLoader__.load({
|
|
|
4271
4336
|
};
|
|
4272
4337
|
const AUTO_CHECK_BOOT_DELAY_MS = 3e3;
|
|
4273
4338
|
const AUTO_CHECK_INTERVAL_MS = 216e5;
|
|
4339
|
+
/** How long the Host's pre-paint palette may survive before it is removed
|
|
4340
|
+
* unconditionally (issue #30 补充). Generous on purpose: removing it EARLY
|
|
4341
|
+
* re-exposes the official palette for one frame, which is the bug. */
|
|
4342
|
+
const BOOT_PALETTE_FALLBACK_MS = 1e4;
|
|
4274
4343
|
let lastAutoResult = null;
|
|
4275
4344
|
let armAutoCheck;
|
|
4276
4345
|
ctx.effect(() => {
|
|
4277
4346
|
let liveBuiltinPick = null;
|
|
4347
|
+
const bootPaletteFallback = window.setTimeout(() => {
|
|
4348
|
+
clearBootPalette();
|
|
4349
|
+
}, BOOT_PALETTE_FALLBACK_MS);
|
|
4278
4350
|
const originalSetTheme = theme.setTheme;
|
|
4279
|
-
const
|
|
4280
|
-
liveBuiltinPick = isBuiltinPreference(id) ? id : null;
|
|
4351
|
+
const commitTheme = (id, record) => {
|
|
4352
|
+
if (record) liveBuiltinPick = isBuiltinPreference(id) ? id : null;
|
|
4281
4353
|
originalSetTheme.call(theme, id);
|
|
4354
|
+
clearBootPalette();
|
|
4355
|
+
};
|
|
4356
|
+
const restoreGuardSetTheme = (id) => {
|
|
4357
|
+
commitTheme(id, true);
|
|
4282
4358
|
};
|
|
4283
4359
|
theme.setTheme = restoreGuardSetTheme;
|
|
4360
|
+
applyRestoredPreference = (id) => {
|
|
4361
|
+
commitTheme(id, false);
|
|
4362
|
+
};
|
|
4284
4363
|
let restorePending = false;
|
|
4364
|
+
let pendingDesired;
|
|
4285
4365
|
const scheduleRestore = (desired) => {
|
|
4366
|
+
pendingDesired = desired;
|
|
4286
4367
|
if (restorePending) return;
|
|
4287
4368
|
restorePending = true;
|
|
4288
4369
|
queueMicrotask(() => {
|
|
4289
4370
|
restorePending = false;
|
|
4371
|
+
const wanted = pendingDesired;
|
|
4372
|
+
pendingDesired = void 0;
|
|
4290
4373
|
const preference = theme.getTheme().preference;
|
|
4291
|
-
if (preference ===
|
|
4374
|
+
if (preference === wanted) {
|
|
4375
|
+
clearBootPalette();
|
|
4376
|
+
return;
|
|
4377
|
+
}
|
|
4292
4378
|
if (builtinPickWins(preference, liveBuiltinPick)) return;
|
|
4293
|
-
ensureThemeRegistered(
|
|
4379
|
+
ensureThemeRegistered(wanted);
|
|
4294
4380
|
try {
|
|
4295
|
-
|
|
4381
|
+
commitTheme(wanted, false);
|
|
4296
4382
|
} catch {}
|
|
4297
4383
|
});
|
|
4298
4384
|
};
|
|
@@ -4301,11 +4387,17 @@ window.__ModuleLoader__.load({
|
|
|
4301
4387
|
const desired = readFlavor();
|
|
4302
4388
|
if (desired === "off") {
|
|
4303
4389
|
const preference = theme.getTheme().preference;
|
|
4304
|
-
if (readExplicitFlavorOff()
|
|
4390
|
+
if (readExplicitFlavorOff()) {
|
|
4391
|
+
clearBootPalette();
|
|
4392
|
+
if (flavorFromThemeId(preference) !== "off") scheduleRestore(readRestoredPreference());
|
|
4393
|
+
}
|
|
4305
4394
|
return;
|
|
4306
4395
|
}
|
|
4307
4396
|
const preference = theme.getTheme().preference;
|
|
4308
|
-
if (preference === desired)
|
|
4397
|
+
if (preference === desired) {
|
|
4398
|
+
clearBootPalette();
|
|
4399
|
+
return;
|
|
4400
|
+
}
|
|
4309
4401
|
if (builtinPickWins(preference, liveBuiltinPick)) return;
|
|
4310
4402
|
scheduleRestore(desired);
|
|
4311
4403
|
};
|
|
@@ -4323,7 +4415,7 @@ window.__ModuleLoader__.load({
|
|
|
4323
4415
|
}
|
|
4324
4416
|
if (flavorFromThemeId(theme.getTheme().preference) === "off") return;
|
|
4325
4417
|
try {
|
|
4326
|
-
|
|
4418
|
+
commitTheme(readRestoredPreference(), false);
|
|
4327
4419
|
} catch {}
|
|
4328
4420
|
};
|
|
4329
4421
|
window.addEventListener("storage", onStorage);
|
|
@@ -4334,6 +4426,15 @@ window.__ModuleLoader__.load({
|
|
|
4334
4426
|
const snapshot = scope.getSnapshot();
|
|
4335
4427
|
const state = durableStateFromSnapshot(snapshot);
|
|
4336
4428
|
if (state === null) return;
|
|
4429
|
+
const revision = snapshot.revision;
|
|
4430
|
+
if (revision !== void 0) {
|
|
4431
|
+
if (revisionKind !== scope.kind) {
|
|
4432
|
+
revisionKind = scope.kind;
|
|
4433
|
+
maxSeenRevision = void 0;
|
|
4434
|
+
}
|
|
4435
|
+
if (maxSeenRevision !== void 0 && revision < maxSeenRevision) return;
|
|
4436
|
+
maxSeenRevision = Math.max(maxSeenRevision ?? revision, revision);
|
|
4437
|
+
}
|
|
4337
4438
|
const local = buildLocalState();
|
|
4338
4439
|
if (pendingLocalPush) {
|
|
4339
4440
|
pendingLocalPush = false;
|
|
@@ -4349,6 +4450,7 @@ window.__ModuleLoader__.load({
|
|
|
4349
4450
|
reapplyThemePrefs();
|
|
4350
4451
|
applyDesired();
|
|
4351
4452
|
syncedSection = settingsSectionFromState(replayed.state);
|
|
4453
|
+
lastDocumentSection = settingsSectionFromState(state);
|
|
4352
4454
|
queuePersist();
|
|
4353
4455
|
return;
|
|
4354
4456
|
}
|
|
@@ -4357,8 +4459,19 @@ window.__ModuleLoader__.load({
|
|
|
4357
4459
|
if (!isDefaultState(local)) queuePersist();
|
|
4358
4460
|
return;
|
|
4359
4461
|
}
|
|
4360
|
-
|
|
4361
|
-
|
|
4462
|
+
const pushCleaned = hasUnpersistableOverrides(snapshot.value?.overrides);
|
|
4463
|
+
const localSection = settingsSectionFromState(local);
|
|
4464
|
+
const documentSection = settingsSectionFromState(state);
|
|
4465
|
+
if (settingsSectionsEqual(localSection, documentSection)) {
|
|
4466
|
+
lastDocumentSection = documentSection;
|
|
4467
|
+
return;
|
|
4468
|
+
}
|
|
4469
|
+
if (pendingLocalSection !== null && !settingsSectionsEqual(pendingLocalSection, documentSection)) return;
|
|
4470
|
+
cancelDurablePersist();
|
|
4471
|
+
baseRevisionTracker.take();
|
|
4472
|
+
pendingLocalSection = null;
|
|
4473
|
+
lastDocumentSection = documentSection;
|
|
4474
|
+
syncedSection = documentSection;
|
|
4362
4475
|
writeFlavor(state.flavor);
|
|
4363
4476
|
glass.applyRemote(state.glass);
|
|
4364
4477
|
writeAutoCheck(state.autoCheck);
|
|
@@ -4368,7 +4481,7 @@ window.__ModuleLoader__.load({
|
|
|
4368
4481
|
emitPrefs();
|
|
4369
4482
|
reapplyThemePrefs();
|
|
4370
4483
|
applyDesired();
|
|
4371
|
-
|
|
4484
|
+
if (pushCleaned) queuePersist();
|
|
4372
4485
|
};
|
|
4373
4486
|
applyScopeSnapshot();
|
|
4374
4487
|
const offScope = scope.subscribe(applyScopeSnapshot);
|
|
@@ -4402,10 +4515,13 @@ window.__ModuleLoader__.load({
|
|
|
4402
4515
|
offGlass();
|
|
4403
4516
|
disposer();
|
|
4404
4517
|
window.removeEventListener("storage", onStorage);
|
|
4518
|
+
window.clearTimeout(bootPaletteFallback);
|
|
4519
|
+
clearBootPalette();
|
|
4405
4520
|
window.clearTimeout(bootTimer);
|
|
4406
4521
|
window.clearInterval(intervalTimer);
|
|
4407
4522
|
cancelDurablePersist();
|
|
4408
4523
|
handleStaleConflict = void 0;
|
|
4524
|
+
applyRestoredPreference = void 0;
|
|
4409
4525
|
armAutoCheck = void 0;
|
|
4410
4526
|
if (theme.setTheme === restoreGuardSetTheme) theme.setTheme = originalSetTheme;
|
|
4411
4527
|
else console.warn("[dsh-catppuccin] theme.setTheme was replaced by another extension; leaving it in place");
|
|
@@ -4426,18 +4542,32 @@ window.__ModuleLoader__.load({
|
|
|
4426
4542
|
if (choice === "off") {
|
|
4427
4543
|
writeFlavor("off");
|
|
4428
4544
|
try {
|
|
4429
|
-
|
|
4545
|
+
if (applyRestoredPreference !== void 0) applyRestoredPreference(readRestoredPreference());
|
|
4546
|
+
else theme.setTheme(readRestoredPreference());
|
|
4430
4547
|
} catch {}
|
|
4431
4548
|
queuePersist();
|
|
4432
4549
|
return;
|
|
4433
4550
|
}
|
|
4434
4551
|
const flavor = flavorInfo(choice);
|
|
4435
4552
|
if (!flavor) return;
|
|
4553
|
+
const previous = readFlavor();
|
|
4436
4554
|
writeFlavor(flavor.themeId);
|
|
4437
4555
|
ensureThemeRegistered(flavor.themeId);
|
|
4438
4556
|
try {
|
|
4439
4557
|
theme.setTheme(flavor.themeId);
|
|
4440
|
-
} catch {
|
|
4558
|
+
} catch {
|
|
4559
|
+
themeDisposers.get(flavor.themeId)?.();
|
|
4560
|
+
themeDisposers.delete(flavor.themeId);
|
|
4561
|
+
registerThemeFor(flavor);
|
|
4562
|
+
try {
|
|
4563
|
+
theme.setTheme(flavor.themeId);
|
|
4564
|
+
} catch {
|
|
4565
|
+
writeFlavor(previous);
|
|
4566
|
+
emitPrefs();
|
|
4567
|
+
emitConflict();
|
|
4568
|
+
return;
|
|
4569
|
+
}
|
|
4570
|
+
}
|
|
4441
4571
|
queuePersist();
|
|
4442
4572
|
},
|
|
4443
4573
|
overrides: overridesSnapshot,
|