fix multi spelling bug

This commit is contained in:
ph1r3754r73r
2026-06-24 10:34:15 -07:00
parent c69cc3c2d3
commit d3b8821090
4 changed files with 115 additions and 2 deletions
+11
View File
@@ -207,6 +207,14 @@ class SpellingAlphabetTool extends Tool {
return 'Enter a name for this spelling alphabet.';
}
var duplicateName = (this.saAlphabets || []).some(function(entry) {
return entry.id !== this.saEditingId &&
String(entry.name || '').trim().toLowerCase() === name.toLowerCase();
}, this);
if (duplicateName) {
return 'Another spelling alphabet already uses this name. Choose a unique name.';
}
var missing = this.saLetters.filter(function(letter) {
return !String(this.saAlphabet[letter] || '').trim();
}, this);
@@ -295,6 +303,9 @@ class SpellingAlphabetTool extends Tool {
onActivate(vueInstance) {
vueInstance.saLoadAlphabets();
if (typeof vueInstance.refreshCustomSpellingTransforms === 'function') {
vueInstance.refreshCustomSpellingTransforms();
}
}
}
+25
View File
@@ -76,6 +76,8 @@ class TransformTool extends Tool {
return true;
})
.map(([key, transform]) => ({
transformKey: key,
customSpellingId: transform.customSpellingId || null,
name: transform.name,
func: transform.func.bind(transform),
preview: transform.preview ? transform.preview.bind(transform) : function() { return '[preview]'; },
@@ -248,6 +250,12 @@ class TransformTool extends Tool {
const transform = this.transforms.find(t => t.name === transformName);
return transform ? transform.category : 'special';
},
getTransformKey: function(transform) {
if (!transform) {
return '';
}
return transform.customSpellingId || transform.transformKey || transform.name;
},
/**
* True if this transform should show the options gear (uses saved prefs + defaults in decoder).
* Falls back to window.transforms when the Vue copy omits configurableOptions.
@@ -644,11 +652,22 @@ class TransformTool extends Tool {
return;
}
const previousCustomCount = (this.transforms || []).filter(function(t) {
return t.category === 'custom_spelling';
}).length;
this.transforms = transformTool.buildTransformsFromWindow();
const categories = transformTool.rebuildTransformCategories(this.transforms);
this.legendCategories = categories.legendCategories;
this.categories = categories.sectionCategories;
const nextCustomCount = this.transforms.filter(function(t) {
return t.category === 'custom_spelling';
}).length;
if (nextCustomCount !== previousCustomCount) {
this.saveCategoryOrder(this.categories);
}
this.$nextTick(() => {
if (typeof this.initializeCategoryNavigation === 'function') {
this.initializeCategoryNavigation();
@@ -719,6 +738,9 @@ class TransformTool extends Tool {
getVueLifecycle() {
return {
mounted() {
if (typeof this.refreshCustomSpellingTransforms === 'function') {
this.refreshCustomSpellingTransforms();
}
this.initializeCategoryNavigation();
// Save initial category order to localStorage if it doesn't exist
@@ -736,6 +758,9 @@ class TransformTool extends Tool {
}
onActivate(vueInstance) {
if (typeof vueInstance.refreshCustomSpellingTransforms === 'function') {
vueInstance.refreshCustomSpellingTransforms();
}
vueInstance.$nextTick(() => {
vueInstance.initializeCategoryNavigation();
});
+2 -2
View File
@@ -416,7 +416,7 @@
</p>
<div class="chaos-overlay" aria-hidden="true"></div>
<div class="transform-buttons">
<div v-for="transform in getTransformsByCategory(category)" :key="transform.name" class="transform-button-group">
<div v-for="transform in getTransformsByCategory(category)" :key="getTransformKey(transform)" class="transform-button-group">
<button
@click="applyTransform(transform, $event)"
:class="'transform-button transform-category-' + category + ' randomizer-button'"
@@ -486,7 +486,7 @@
</span>
</h4>
<div class="transform-buttons">
<div v-for="transform in getTransformsByCategory(category)" :key="transform.name" class="transform-button-group">
<div v-for="transform in getTransformsByCategory(category)" :key="getTransformKey(transform)" class="transform-button-group">
<button
@click="applyTransform(transform, $event)"
:class="'transform-button transform-category-' + category"
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env node
const assert = require('assert');
const path = require('path');
const vm = require('vm');
const fs = require('fs');
function createContext() {
const store = {};
const ctx = {
window: null,
globalThis: null,
localStorage: {
getItem: (key) => store[key] || null,
setItem: (key, value) => { store[key] = value; }
},
console
};
ctx.window = ctx;
ctx.globalThis = ctx;
return { ctx, store };
}
function loadScript(ctx, relativePath) {
const code = fs.readFileSync(path.join(__dirname, '..', relativePath), 'utf8');
vm.runInContext(code, vm.createContext(ctx), { filename: relativePath });
}
function buildAlphabet(prefix) {
const alphabet = {};
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').forEach((letter, index) => {
alphabet[letter] = prefix + letter + index;
});
return alphabet;
}
const { ctx } = createContext();
loadScript(ctx, 'dist/js/bundles/transforms-bundle.js');
loadScript(ctx, 'js/core/spellingAlphabetTransform.js');
loadScript(ctx, 'js/core/customSpellingAlphabets.js');
const first = ctx.CustomSpellingAlphabets.saveMapping({
name: 'Nautical Spelling Alphabet',
category: 'nautical',
alphabet: buildAlphabet('N')
});
const second = ctx.CustomSpellingAlphabets.saveMapping({
name: 'Kitchen Spelling Alphabet',
category: 'kitchen',
alphabet: buildAlphabet('K')
});
assert.strictEqual(ctx.CustomSpellingAlphabets.loadAll().length, 2, 'Should persist multiple alphabets');
const customKeys = Object.keys(ctx.window.transforms).filter((key) => key.indexOf('custom_spelling_') === 0);
assert.strictEqual(customKeys.length, 2, 'Each saved alphabet should register as its own transform');
const names = customKeys.map((key) => ctx.window.transforms[key].name).sort();
assert.deepStrictEqual(names, [
'Kitchen Spelling Alphabet',
'Nautical Spelling Alphabet'
]);
customKeys.forEach((key) => {
const transform = ctx.window.transforms[key];
assert.strictEqual(transform.category, 'custom_spelling');
assert.ok(transform.customSpellingId, 'Custom spelling transforms should expose customSpellingId');
assert.strictEqual(typeof transform.func, 'function');
});
ctx.CustomSpellingAlphabets.deleteMapping(first.id);
assert.strictEqual(ctx.CustomSpellingAlphabets.loadAll().length, 1);
const remainingKeys = Object.keys(ctx.window.transforms).filter((key) => key.indexOf('custom_spelling_') === 0);
assert.strictEqual(remainingKeys.length, 1);
assert.strictEqual(ctx.window.transforms[remainingKeys[0]].name, 'Kitchen Spelling Alphabet');
console.log('Custom spelling transform tests passed');