mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-10-21 05:01:26 -07:00
fix(hachidori): keep the hachidori tag alongside SubMiner's Anki tags
- Untouched default templates now get configured tags plus `hachidori` instead of replacing it - Tags edited in Hachidori settings are left as written - Update Anki integration docs and changelog fragment
This commit is contained in:
4 files changed
+16
-4
No files matched your search
@@ -4,7 +4,7 @@ area: dictionary
|
|||||||
- Added a bundled Hachidori dictionary backend alongside the default Yomitan backend. Select it with `dictionaryBackend` and restart SubMiner.
|
- Added a bundled Hachidori dictionary backend alongside the default Yomitan backend. Select it with `dictionaryBackend` and restart SubMiner.
|
||||||
- The tray and dictionary-settings shortcut follow the selected backend. `--hachidori` opens Hachidori settings, while `--yomitan` opens Yomitan settings unless a read-only external Yomitan profile is configured. This restriction also applies with Hachidori active, without blocking Hachidori settings.
|
- The tray and dictionary-settings shortcut follow the selected backend. `--hachidori` opens Hachidori settings, while `--yomitan` opens Yomitan settings unless a read-only external Yomitan profile is configured. This restriction also applies with Hachidori active, without blocking Hachidori settings.
|
||||||
- Hachidori integrates with subtitle scanning, popup controls, lookup tracking, character dictionaries, and Anki media enrichment, with separate dictionaries and settings for each backend. Character dictionaries reach a linked host over the link (Hachidori 0.2.3 or later, or a current Docker host), retry busy imports, and replace the previous dictionary only after a successful import. Older hosts report where to import the dictionary manually.
|
- Hachidori integrates with subtitle scanning, popup controls, lookup tracking, character dictionaries, and Anki media enrichment, with separate dictionaries and settings for each backend. Character dictionaries reach a linked host over the link (Hachidori 0.2.3 or later, or a current Docker host), retry busy imports, and replace the previous dictionary only after a successful import. Older hosts report where to import the dictionary manually.
|
||||||
- Hachidori auto-populates its first Anki template from SubMiner's deck, tags, and field mappings, detects an unambiguous matching note type, and preserves existing custom templates apart from the deck, which follows `ankiConnect.deck` so polling mode enriches Hachidori cards. Anki discovery retries after an unavailable connection.
|
- Hachidori auto-populates its first Anki template from SubMiner's deck, tags (kept alongside its own `hachidori` tag), and field mappings, detects an unambiguous matching note type, and preserves existing custom templates apart from the deck, which follows `ankiConnect.deck` so polling mode enriches Hachidori cards. Anki discovery retries after an unavailable connection.
|
||||||
- Hachidori saves downloadable word audio before sending a note through SubMiner's Anki proxy, so freshly mined animated cards include the word-audio delay.
|
- Hachidori saves downloadable word audio before sending a note through SubMiner's Anki proxy, so freshly mined animated cards include the word-audio delay.
|
||||||
- Both bundled dictionary backends reload their background code on startup so extension updates take effect while preserving installed dictionaries and settings. Failed Yomitan connection-setting updates can be retried without manually resetting the managed Anki endpoint.
|
- Both bundled dictionary backends reload their background code on startup so extension updates take effect while preserving installed dictionaries and settings. Failed Yomitan connection-setting updates can be retried without manually resetting the managed Anki endpoint.
|
||||||
- First-run setup remembers each backend that finished it, including when reopened for legacy plugin cleanup, so switching back does not repeat setup, and the launcher gates playback on the backend the running app started with. Current incomplete or cancelled setup takes precedence over stale completion history. A running Yomitan session keeps using its external profile until it restarts into Hachidori.
|
- First-run setup remembers each backend that finished it, including when reopened for legacy plugin cleanup, so switching back does not repeat setup, and the launcher gates playback on the backend the running app started with. Current incomplete or cancelled setup takes precedence over stale completion history. A running Yomitan session keeps using its external profile until it restarts into Hachidori.
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ Clients must send notes to the proxy (`http://127.0.0.1:8766` here), not to Anki
|
|||||||
With the [Hachidori backend](/usage#hachidori-setup), SubMiner fills Hachidori's first Anki template from your `ankiConnect` settings on startup and whenever you open Hachidori Settings:
|
With the [Hachidori backend](/usage#hachidori-setup), SubMiner fills Hachidori's first Anki template from your `ankiConnect` settings on startup and whenever you open Hachidori Settings:
|
||||||
|
|
||||||
- The deck always follows `ankiConnect.deck`, because polling only looks for new cards in that deck.
|
- The deck always follows `ankiConnect.deck`, because polling only looks for new cards in that deck.
|
||||||
- Configured tags go into untouched defaults.
|
- While the template still has Hachidori's default `hachidori` tag, the configured tags are added ahead of it so cards carry both. Tags you edit in Hachidori settings are kept as written.
|
||||||
- Missing word, sentence, pronunciation-audio, and picture mappings are filled with fields that exist in Anki. Pronunciation uses `fields.wordAudio`, or `fields.audio` when no word-audio field is set.
|
- Missing word, sentence, pronunciation-audio, and picture mappings are filled with fields that exist in Anki. Pronunciation uses `fields.wordAudio`, or `fields.audio` when no word-audio field is set.
|
||||||
- If the note type is unset, SubMiner picks the one note type that has your word and sentence fields. Enabled Lapis, Kiku, or Senren narrows the search. A fresh mapping also gets Hachidori's matching preset for readings, definitions, and other known fields.
|
- If the note type is unset, SubMiner picks the one note type that has your word and sentence fields. Enabled Lapis, Kiku, or Senren narrows the search. A fresh mapping also gets Hachidori's matching preset for readings, definitions, and other known fields.
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ test('fresh Hachidori settings inherit deck, tags, a unique model and configured
|
|||||||
assert.deepEqual(await h.sync(), { updated: true, matched: true, pending: false });
|
assert.deepEqual(await h.sync(), { updated: true, matched: true, pending: false });
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
await h.run('[options.anki.url, options.anki.deck, options.anki.model, options.anki.tags]'),
|
await h.run('[options.anki.url, options.anki.deck, options.anki.model, options.anki.tags]'),
|
||||||
['http://127.0.0.1:8766', 'Mining', 'Japanese', config.tags],
|
['http://127.0.0.1:8766', 'Mining', 'Japanese', [...config.tags, 'hachidori']],
|
||||||
);
|
);
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
await h.run(
|
await h.run(
|
||||||
@@ -102,6 +102,16 @@ test('fresh Hachidori settings inherit deck, tags, a unique model and configured
|
|||||||
assert.equal(await h.run('writes'), 1);
|
assert.equal(await h.run('writes'), 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('leaves tags edited in Hachidori settings alone', async () => {
|
||||||
|
const h = await harness({
|
||||||
|
templates: [
|
||||||
|
{ id: 'default', name: 'Default', deck: 'Mining', model: 'Japanese', tags: ['SubMiner'] },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
await h.sync();
|
||||||
|
assert.deepEqual(await h.run('options.anki.tags'), ['SubMiner']);
|
||||||
|
});
|
||||||
|
|
||||||
// SubMiner's new-card polling only watches ankiConnect.deck, so the first
|
// SubMiner's new-card polling only watches ankiConnect.deck, so the first
|
||||||
// template's deck follows it the way Yomitan's term card deck does.
|
// template's deck follows it the way Yomitan's term card deck does.
|
||||||
test('moves the first template to the SubMiner deck and preserves the rest of custom templates', async () => {
|
test('moves the first template to the SubMiner deck and preserves the rest of custom templates', async () => {
|
||||||
|
|||||||
@@ -49,8 +49,10 @@ export const HACHIDORI_ANKI_SETTINGS_SCRIPT = String.raw`
|
|||||||
// SubMiner's new-card polling only watches its configured deck, so the
|
// SubMiner's new-card polling only watches its configured deck, so the
|
||||||
// first template follows it like Yomitan's term card deck.
|
// first template follows it like Yomitan's term card deck.
|
||||||
if (deck) template.deck = deck;
|
if (deck) template.deck = deck;
|
||||||
|
// SubMiner's tags join Hachidori's own so cards show which backend mined
|
||||||
|
// them. Only the untouched default is filled; edits in Hachidori settings win.
|
||||||
if (hints?.tags && JSON.stringify(first.tags) === JSON.stringify(['hachidori'])) {
|
if (hints?.tags && JSON.stringify(first.tags) === JSON.stringify(['hachidori'])) {
|
||||||
template.tags = [...hints.tags];
|
template.tags = [...new Set([...hints.tags, 'hachidori'])];
|
||||||
}
|
}
|
||||||
let pending = false;
|
let pending = false;
|
||||||
// Advanced templates include intentionally blank fields. Preserve them
|
// Advanced templates include intentionally blank fields. Preserve them
|
||||||
|
|||||||
Reference in new issue
Block a user