diff --git a/.github/workflows/broken-links.yml b/.github/workflows/broken-links.yml index c337d99164..4c3eeeb2da 100644 --- a/.github/workflows/broken-links.yml +++ b/.github/workflows/broken-links.yml @@ -21,7 +21,7 @@ jobs: run: npm ci - name: Build Legal run: npm run license-report:html - - uses: lycheeverse/lychee-action@v1.10.0 + - uses: lycheeverse/lychee-action@v2.0.0 with: fail: true jobSummary: false diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3c82761f62..aab0563064 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -51,7 +51,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3.26.10 + uses: github/codeql-action/init@v3.26.12 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -65,7 +65,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v3.26.10 + uses: github/codeql-action/autobuild@v3.26.12 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -78,6 +78,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3.26.10 + uses: github/codeql-action/analyze@v3.26.12 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 28f4f89f4f..22cb6238b8 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -64,6 +64,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@cf5b0a9041d3c1d336516f1944c96d96598193cc # v2.22.12 + uses: github/codeql-action/upload-sarif@572cc5268d94f11b89e12e7a166cf93275856072 # v2.22.12 with: sarif_file: results.sarif diff --git a/README.md b/README.md index 931b73127d..056d405186 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Get Yomitan for Edge](https://img.shields.io/badge/dynamic/json?logo=puzzle&label=get%20yomitan%20for%20edge&style=for-the-badge&query=%24.version&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Fidelnfbbmikgfiejhgmddlbkfgiifnnn)](https://microsoftedge.microsoft.com/addons/detail/yomitan/idelnfbbmikgfiejhgmddlbkfgiifnnn) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/yomidevs/yomitan/badge?style=for-the-badge)](https://securityscorecards.dev/viewer/?uri=github.com/yomidevs/yomitan) -General: [![Discord](https://dcbadge.vercel.app/api/server/YkQrXW6TXF?style=for-the-badge)](https://discord.gg/YkQrXW6TXF) Japanese: [![Discord](https://dcbadge.vercel.app/api/server/UGNPMDE7zC?style=for-the-badge)](https://discord.gg/UGNPMDE7zC) +[![Discord](https://dcbadge.vercel.app/api/server/YkQrXW6TXF?style=for-the-badge)](https://discord.gg/YkQrXW6TXF) # Visit [yomitan.wiki](https://yomitan.wiki) to learn more! diff --git a/ext/css/search.css b/ext/css/search.css index 81e4a74c78..7327b89ac1 100644 --- a/ext/css/search.css +++ b/ext/css/search.css @@ -135,6 +135,48 @@ h1 { --icon-size: 16px 16px; } +.clear-button { + flex: 0 0 auto; + position: relative; + width: 2.5em; + height: var(--search-textbox-height); + min-height: var(--search-textbox-min-height); + max-height: var(--search-textbox-max-height); + background-color: var(--input-background-color); + border: 0; + padding: 0; + margin: 0; + cursor: pointer; + outline: none; + transition: background-color var(--animation-duration) ease-in-out; + border-radius: 0; +} +.clear-button:hover, +.clear-button:focus { + background-color: var(--input-background-color-dark); +} +.clear-button:focus:not(:focus-visible):not(:hover) { + background-color: var(--input-background-color); +} +.clear-button:focus-visible { + background-color: var(--input-background-color-dark); +} +.clear-button:active, +.clear-button:active:focus { + background-color: var(--input-background-color-darker); +} + +.clear-button>.icon { + display: block; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + background-color: var(--button-default-icon-color); + --icon-size: 16px 16px; +} + /* Search options */ #search-settings-button>.icon { display: block; diff --git a/ext/js/dictionary/dictionary-importer.js b/ext/js/dictionary/dictionary-importer.js index 13fbb7078c..e8a72ba821 100644 --- a/ext/js/dictionary/dictionary-importer.js +++ b/ext/js/dictionary/dictionary-importer.js @@ -373,10 +373,9 @@ export class DictionaryImporter { * @returns {ExtensionError} */ _formatAjvSchemaError(schema, fileName) { - const e2 = new ExtensionError(`Dictionary has invalid data in '${fileName}'`); - e2.data = schema.errors; - - return e2; + const e = new ExtensionError(`Dictionary has invalid data in '${fileName}' '${JSON.stringify(schema.errors)}'`); + e.data = schema.errors; + return e; } /** diff --git a/ext/js/display/display.js b/ext/js/display/display.js index 2f90189d90..3f6d893a8d 100644 --- a/ext/js/display/display.js +++ b/ext/js/display/display.js @@ -784,11 +784,14 @@ export class Display extends EventDispatcher { async _onStateChanged() { if (this._historyChangeIgnore) { return; } + performance.mark('display:onStateChanged:start'); + /** @type {?import('core').TokenObject} */ const token = {}; // Unique identifier token this._setContentToken = token; try { // Clear + performance.mark('display:clear:start'); this._closePopups(); this._closeAllPopupMenus(); this._eventListeners.removeAllEventListeners(); @@ -799,8 +802,11 @@ export class Display extends EventDispatcher { this._dictionaryEntries = []; this._dictionaryEntryNodes = []; this._elementOverflowController.clearElements(); + performance.mark('display:clear:end'); + performance.measure('display:clear', 'display:clear:start', 'display:clear:end'); // Prepare + performance.mark('display:prepare:start'); const urlSearchParams = new URLSearchParams(location.search); let type = urlSearchParams.get('type'); if (type === null && urlSearchParams.get('query') !== null) { type = 'terms'; } @@ -809,7 +815,10 @@ export class Display extends EventDispatcher { this._queryParserVisibleOverride = (fullVisible === null ? null : (fullVisible !== 'false')); this._historyHasChanged = true; + performance.mark('display:prepare:end'); + performance.measure('display:prepare', 'display:prepare:start', 'display:prepare:end'); + performance.mark('display:setContent:start'); // Set content switch (type) { case 'terms': @@ -826,9 +835,13 @@ export class Display extends EventDispatcher { this._clearContent(); break; } + performance.mark('display:setContent:end'); + performance.measure('display:setContent', 'display:setContent:start', 'display:setContent:end'); } catch (e) { this.onError(toError(e)); } + performance.mark('display:onStateChanged:end'); + performance.measure('display:onStateChanged', 'display:onStateChanged:start', 'display:onStateChanged:end'); } /** @@ -1309,6 +1322,7 @@ export class Display extends EventDispatcher { const hasEnabledDictionaries = this._options ? this._options.dictionaries.some(({enabled}) => enabled) : false; // Set query + performance.mark('display:setQuery:start'); let query = urlSearchParams.get('query'); if (query === null) { query = ''; } let queryFull = urlSearchParams.get('full'); @@ -1320,6 +1334,8 @@ export class Display extends EventDispatcher { queryOffset = Number.isFinite(queryOffset) ? Math.max(0, Math.min(queryFull.length - query.length, queryOffset)) : 0; } this._setQuery(query, queryFull, queryOffset); + performance.mark('display:setQuery:end'); + performance.measure('display:setQuery', 'display:setQuery:start', 'display:setQuery:end'); let {state, content} = this._history; let changeHistory = false; @@ -1384,9 +1400,12 @@ export class Display extends EventDispatcher { const container = this._container; container.textContent = ''; + performance.mark('display:contentUpdate:start'); this._triggerContentUpdateStart(); for (let i = 0, ii = dictionaryEntries.length; i < ii; ++i) { + performance.mark('display:createEntry:start'); + if (i > 0) { await promiseTimeout(1); if (this._setContentToken !== token) { return; } @@ -1408,6 +1427,9 @@ export class Display extends EventDispatcher { } this._elementOverflowController.addElements(entry); + + performance.mark('display:createEntry:end'); + performance.measure('display:createEntry', 'display:createEntry:start', 'display:createEntry:end'); } if (typeof scrollX === 'number' || typeof scrollY === 'number') { @@ -1419,6 +1441,8 @@ export class Display extends EventDispatcher { } this._triggerContentUpdateComplete(); + performance.mark('display:contentUpdate:end'); + performance.measure('display:contentUpdate', 'display:contentUpdate:start', 'display:contentUpdate:end'); } /** */ diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js index 925f9e0533..50175cb9e6 100644 --- a/ext/js/display/search-display-controller.js +++ b/ext/js/display/search-display-controller.js @@ -38,6 +38,8 @@ export class SearchDisplayController { /** @type {HTMLButtonElement} */ this._searchButton = querySelectorNotNull(document, '#search-button'); /** @type {HTMLButtonElement} */ + this._clearButton = querySelectorNotNull(document, '#clear-button'); + /** @type {HTMLButtonElement} */ this._searchBackButton = querySelectorNotNull(document, '#search-back-button'); /** @type {HTMLTextAreaElement} */ this._queryInput = querySelectorNotNull(document, '#search-textbox'); @@ -104,6 +106,8 @@ export class SearchDisplayController { this._display.setHistorySettings({useBrowserHistory: true}); this._searchButton.addEventListener('click', this._onSearch.bind(this), false); + this._clearButton.addEventListener('click', this._onClear.bind(this), false); + this._searchBackButton.addEventListener('click', this._onSearchBackButtonClick.bind(this), false); this._wanakanaEnableCheckbox.addEventListener('change', this._onWanakanaEnableChange.bind(this)); window.addEventListener('copy', this._onCopy.bind(this)); @@ -268,6 +272,15 @@ export class SearchDisplayController { this._search(true, 'new', true, null); } + /** + * @param {MouseEvent} e + */ + _onClear(e) { + e.preventDefault(); + this._queryInput.value = ''; + this._queryInput.focus(); + } + /** */ _onSearchBackButtonClick() { this._display.history.back(); @@ -617,7 +630,7 @@ export class SearchDisplayController { */ _updateSearchHeight(shrink) { const searchTextbox = this._queryInput; - const searchItems = [this._queryInput, this._searchButton, this._searchBackButton]; + const searchItems = [this._queryInput, this._searchButton, this._searchBackButton, this._clearButton]; if (shrink) { for (const searchButton of searchItems) { diff --git a/ext/js/language/ja/japanese-transforms.js b/ext/js/language/ja/japanese-transforms.js index 69cabe82b1..6288822639 100644 --- a/ext/js/language/ja/japanese-transforms.js +++ b/ext/js/language/ja/japanese-transforms.js @@ -25,7 +25,7 @@ const passiveEnglishDescription = '1. Indicates an action received from an actio '2. Expresses respect for the subject of action performer.\n'; const ikuVerbs = ['いく', '行く', '逝く', '往く']; -const godanUSpecialVerbs = ['こう', 'とう', '請う', '乞う', '問う', '訪う', '宣う', '曰う', '給う', '賜う', '揺蕩う']; +const godanUSpecialVerbs = ['こう', 'とう', '請う', '乞う', '恋う', '問う', '訪う', '宣う', '曰う', '給う', '賜う', '揺蕩う']; const fuVerbTeConjugations = [ ['のたまう', 'のたもう'], ['たまう', 'たもう'], diff --git a/ext/js/language/zh/chinese.js b/ext/js/language/zh/chinese.js index 8c5dd206fe..ca89de1ec9 100644 --- a/ext/js/language/zh/chinese.js +++ b/ext/js/language/zh/chinese.js @@ -71,5 +71,5 @@ export function isCodePointChinese(codePoint) { /** @type {import('language').ReadingNormalizer} */ export function normalizePinyin(str) { - return str.normalize('NFC').toLowerCase().replace(/[\s・:]|\/\//g, ''); + return str.normalize('NFC').toLowerCase().replace(/[\s・:'’-]|\/\//g, ''); } diff --git a/ext/js/pages/settings/dictionary-import-controller.js b/ext/js/pages/settings/dictionary-import-controller.js index 15bc4b908f..f2e0623550 100644 --- a/ext/js/pages/settings/dictionary-import-controller.js +++ b/ext/js/pages/settings/dictionary-import-controller.js @@ -208,6 +208,10 @@ export class DictionaryImportController { _renderRecommendedDictionaryGroup(recommendedDictionaries, dictionariesList, installedDictionaryNames, installedDictionaryDownloadUrls) { const dictionariesListParent = dictionariesList.parentElement; dictionariesList.innerHTML = ''; + // Hide section if no dictionaries are available + if (dictionariesListParent) { + dictionariesListParent.hidden = recommendedDictionaries.length === 0; + } for (const dictionary of recommendedDictionaries) { if (dictionariesList) { if (dictionariesListParent) { diff --git a/ext/js/templates/anki-template-renderer.js b/ext/js/templates/anki-template-renderer.js index d526a1d13e..f359f858e3 100644 --- a/ext/js/templates/anki-template-renderer.js +++ b/ext/js/templates/anki-template-renderer.js @@ -285,7 +285,11 @@ export class AnkiTemplateRenderer { */ _mergeTags(args) { const [object, isGroupMode, isMergeMode] = /** @type {[object: import('anki-templates').TermDictionaryEntry, isGroupMode: boolean, isMergeMode: boolean]} */ (args); + /** @type {import('anki-templates').Tag[][]} */ const tagSources = []; + if (Array.isArray(object.termTags)) { + tagSources.push(object.termTags); + } if (isGroupMode || isMergeMode) { const {definitions} = object; if (Array.isArray(definitions)) { @@ -294,12 +298,13 @@ export class AnkiTemplateRenderer { } } } else { - tagSources.push(object.definitionTags); + if (Array.isArray(object.definitionTags)) { + tagSources.push(object.definitionTags); + } } const tags = new Set(); for (const tagSource of tagSources) { - if (!Array.isArray(tagSource)) { continue; } for (const tag of tagSource) { tags.add(tag.name); } diff --git a/ext/search.html b/ext/search.html index 958b8a2858..7e9be81e20 100644 --- a/ext/search.html +++ b/ext/search.html @@ -55,6 +55,7 @@

Yomitan Search

+
diff --git a/test/data/anki-note-builder-test-results.json b/test/data/anki-note-builder-test-results.json index 428b878a90..a7e954152d 100644 --- a/test/data/anki-note-builder-test-results.json +++ b/test/data/anki-note-builder-test-results.json @@ -111,7 +111,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打cloze-suffix", "sentence-furigana": "cloze-prefix打cloze-suffix", - "tags": "n", + "tags": "E1, n", "url": "url:" }, { @@ -153,7 +153,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打cloze-suffix", "sentence-furigana": "cloze-prefix打cloze-suffix", - "tags": "abbr, n", + "tags": "E1, abbr, n", "url": "url:" } ] @@ -200,7 +200,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打つcloze-suffix", "sentence-furigana": "cloze-prefix打つcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -242,7 +242,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打つcloze-suffix", "sentence-furigana": "cloze-prefix打つcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -284,7 +284,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打つcloze-suffix", "sentence-furigana": "cloze-prefix打つcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -326,7 +326,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打つcloze-suffix", "sentence-furigana": "cloze-prefix打つcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -368,7 +368,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打cloze-suffix", "sentence-furigana": "cloze-prefix打cloze-suffix", - "tags": "n", + "tags": "E1, n", "url": "url:" }, { @@ -410,7 +410,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打cloze-suffix", "sentence-furigana": "cloze-prefix打cloze-suffix", - "tags": "abbr, n", + "tags": "E1, abbr, n", "url": "url:" } ] @@ -457,7 +457,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -499,7 +499,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -541,7 +541,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -583,7 +583,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -625,7 +625,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", "sentence-furigana": "cloze-prefix打ちcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -667,7 +667,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", "sentence-furigana": "cloze-prefix打ちcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -709,7 +709,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", "sentence-furigana": "cloze-prefix打ちcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -751,7 +751,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", "sentence-furigana": "cloze-prefix打ちcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -793,7 +793,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打cloze-suffix", "sentence-furigana": "cloze-prefix打cloze-suffix", - "tags": "n", + "tags": "E1, n", "url": "url:" }, { @@ -835,7 +835,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打cloze-suffix", "sentence-furigana": "cloze-prefix打cloze-suffix", - "tags": "abbr, n", + "tags": "E1, abbr, n", "url": "url:" } ] @@ -882,7 +882,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix画像cloze-suffix", "sentence-furigana": "cloze-prefix画像cloze-suffix", - "tags": "n", + "tags": "E1, P, n", "url": "url:" } ] @@ -929,7 +929,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixだcloze-suffix", "sentence-furigana": "cloze-prefixだcloze-suffix", - "tags": "n", + "tags": "E1, n", "url": "url:" } ] @@ -976,7 +976,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixダースcloze-suffix", "sentence-furigana": "cloze-prefixダースcloze-suffix", - "tags": "abbr, n", + "tags": "E1, abbr, n", "url": "url:" }, { @@ -1018,7 +1018,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixダcloze-suffix", "sentence-furigana": "cloze-prefixダcloze-suffix", - "tags": "n", + "tags": "E1, n", "url": "url:" } ] @@ -1065,7 +1065,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixうつcloze-suffix", "sentence-furigana": "cloze-prefixうつcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -1107,7 +1107,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixうつcloze-suffix", "sentence-furigana": "cloze-prefixうつcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" } ] @@ -1154,7 +1154,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixぶつcloze-suffix", "sentence-furigana": "cloze-prefixぶつcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -1196,7 +1196,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixぶつcloze-suffix", "sentence-furigana": "cloze-prefixぶつcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" } ] @@ -1243,7 +1243,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixうちこむcloze-suffix", "sentence-furigana": "cloze-prefixうちこむcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -1285,7 +1285,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixうちこむcloze-suffix", "sentence-furigana": "cloze-prefixうちこむcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -1327,7 +1327,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixうちcloze-suffix", "sentence-furigana": "cloze-prefixうちcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -1369,7 +1369,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixうちcloze-suffix", "sentence-furigana": "cloze-prefixうちcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" } ] @@ -1416,7 +1416,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixぶちこむcloze-suffix", "sentence-furigana": "cloze-prefixぶちこむcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -1458,7 +1458,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixぶちこむcloze-suffix", "sentence-furigana": "cloze-prefixぶちこむcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -1500,7 +1500,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixぶちcloze-suffix", "sentence-furigana": "cloze-prefixぶちcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -1542,7 +1542,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixぶちcloze-suffix", "sentence-furigana": "cloze-prefixぶちcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" } ] @@ -1589,7 +1589,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixがぞうcloze-suffix", "sentence-furigana": "cloze-prefixがぞうcloze-suffix", - "tags": "n", + "tags": "E1, P, n", "url": "url:" } ] @@ -1648,7 +1648,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", - "tags": "vt", + "tags": "E1, E2, P, vt", "url": "url:" }, { @@ -1690,7 +1690,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", - "tags": "vt", + "tags": "E1, E2, P, vt", "url": "url:" }, { @@ -1732,7 +1732,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", "sentence-furigana": "cloze-prefix打ちcloze-suffix", - "tags": "vt", + "tags": "E1, E2, P, vt", "url": "url:" }, { @@ -1774,7 +1774,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", "sentence-furigana": "cloze-prefix打ちcloze-suffix", - "tags": "vt", + "tags": "E1, E2, P, vt", "url": "url:" }, { @@ -1816,7 +1816,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打cloze-suffix", "sentence-furigana": "cloze-prefix打cloze-suffix", - "tags": "n", + "tags": "E1, n", "url": "url:" }, { @@ -1858,7 +1858,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打cloze-suffix", "sentence-furigana": "cloze-prefix打cloze-suffix", - "tags": "abbr, n", + "tags": "E1, abbr, n", "url": "url:" } ] @@ -2078,7 +2078,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ち込んでいませんでしたcloze-suffix", "sentence-furigana": "cloze-prefix打ち込んでいませんでしたcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -2120,7 +2120,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ち込んでいませんでしたcloze-suffix", "sentence-furigana": "cloze-prefix打ち込んでいませんでしたcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -2162,7 +2162,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ち込んでいませんでしたcloze-suffix", "sentence-furigana": "cloze-prefix打ち込んでいませんでしたcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -2204,7 +2204,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ち込んでいませんでしたcloze-suffix", "sentence-furigana": "cloze-prefix打ち込んでいませんでしたcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -2246,7 +2246,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", "sentence-furigana": "cloze-prefix打ちcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -2288,7 +2288,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", "sentence-furigana": "cloze-prefix打ちcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -2330,7 +2330,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", "sentence-furigana": "cloze-prefix打ちcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -2372,7 +2372,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", "sentence-furigana": "cloze-prefix打ちcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -2414,7 +2414,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打cloze-suffix", "sentence-furigana": "cloze-prefix打cloze-suffix", - "tags": "n", + "tags": "E1, n", "url": "url:" }, { @@ -2456,7 +2456,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打cloze-suffix", "sentence-furigana": "cloze-prefix打cloze-suffix", - "tags": "abbr, n", + "tags": "E1, abbr, n", "url": "url:" } ] @@ -2503,7 +2503,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打(う)ち込(こ)むcloze-suffix", "sentence-furigana": "cloze-prefix打(う)ち込(こ)むcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -2545,7 +2545,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打(う)ち込(こ)むcloze-suffix", "sentence-furigana": "cloze-prefix打(う)ち込(こ)むcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -2587,7 +2587,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打(う)ち込(こ)むcloze-suffix", "sentence-furigana": "cloze-prefix打(う)ち込(こ)むcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -2629,7 +2629,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打(う)ち込(こ)むcloze-suffix", "sentence-furigana": "cloze-prefix打(う)ち込(こ)むcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -2671,7 +2671,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打(う)ちcloze-suffix", "sentence-furigana": "cloze-prefix打(う)ちcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -2713,7 +2713,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打(う)ちcloze-suffix", "sentence-furigana": "cloze-prefix打(う)ちcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -2755,7 +2755,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打(う)ちcloze-suffix", "sentence-furigana": "cloze-prefix打(う)ちcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -2797,7 +2797,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打(う)ちcloze-suffix", "sentence-furigana": "cloze-prefix打(う)ちcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -2839,7 +2839,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打(う)cloze-suffix", "sentence-furigana": "cloze-prefix打(う)cloze-suffix", - "tags": "n", + "tags": "E1, n", "url": "url:" }, { @@ -2881,7 +2881,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix打(う)cloze-suffix", "sentence-furigana": "cloze-prefix打(う)cloze-suffix", - "tags": "abbr, n", + "tags": "E1, abbr, n", "url": "url:" } ] @@ -2928,7 +2928,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", "sentence-furigana": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -2970,7 +2970,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", "sentence-furigana": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -3012,7 +3012,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", "sentence-furigana": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -3054,7 +3054,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", "sentence-furigana": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -3096,7 +3096,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix(打)(ち)cloze-suffix", "sentence-furigana": "cloze-prefix(打)(ち)cloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -3138,7 +3138,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix(打)(ち)cloze-suffix", "sentence-furigana": "cloze-prefix(打)(ち)cloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -3180,7 +3180,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix(打)(ち)cloze-suffix", "sentence-furigana": "cloze-prefix(打)(ち)cloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -3222,7 +3222,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix(打)(ち)cloze-suffix", "sentence-furigana": "cloze-prefix(打)(ち)cloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" }, { @@ -3264,7 +3264,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix(打)cloze-suffix", "sentence-furigana": "cloze-prefix(打)cloze-suffix", - "tags": "n", + "tags": "E1, n", "url": "url:" }, { @@ -3306,7 +3306,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix(打)cloze-suffix", "sentence-furigana": "cloze-prefix(打)cloze-suffix", - "tags": "abbr, n", + "tags": "E1, abbr, n", "url": "url:" } ] @@ -3353,7 +3353,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixtestcloze-suffix", "sentence-furigana": "cloze-prefixtestcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" } ] @@ -3400,7 +3400,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixつtestcloze-suffix", "sentence-furigana": "cloze-prefixつtestcloze-suffix", - "tags": "n", + "tags": "E1, P, n", "url": "url:" } ] @@ -3447,7 +3447,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixtestましたcloze-suffix", "sentence-furigana": "cloze-prefixtestましたcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" } ] @@ -3865,7 +3865,7 @@ "popup-selection-text": "", "sentence": "cloze-prefix構造cloze-suffix", "sentence-furigana": "cloze-prefix構造cloze-suffix", - "tags": "n", + "tags": "E1, P, n", "url": "url:" } ] @@ -4100,7 +4100,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixutsucloze-suffix", "sentence-furigana": "cloze-prefixutsucloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -4142,7 +4142,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixutsucloze-suffix", "sentence-furigana": "cloze-prefixutsucloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" } ] @@ -4189,7 +4189,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixウツcloze-suffix", "sentence-furigana": "cloze-prefixウツcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -4231,7 +4231,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixウツcloze-suffix", "sentence-furigana": "cloze-prefixウツcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" } ] @@ -4278,7 +4278,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixてきすとcloze-suffix", "sentence-furigana": "cloze-prefixてきすとcloze-suffix", - "tags": "n", + "tags": "E1, P, n", "url": "url:" } ] @@ -4325,7 +4325,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixウツcloze-suffix", "sentence-furigana": "cloze-prefixウツcloze-suffix", - "tags": "vt", + "tags": "E1, P, vt", "url": "url:" }, { @@ -4367,7 +4367,7 @@ "popup-selection-text": "", "sentence": "cloze-prefixウツcloze-suffix", "sentence-furigana": "cloze-prefixウツcloze-suffix", - "tags": "vt", + "tags": "E2, P, vt", "url": "url:" } ] diff --git a/test/language/chinese-reading-normalizer.test.js b/test/language/chinese-reading-normalizer.test.js index 12eb47e6dc..97d4fca27b 100644 --- a/test/language/chinese-reading-normalizer.test.js +++ b/test/language/chinese-reading-normalizer.test.js @@ -25,6 +25,9 @@ const tests = [ ['wán:zhěng', 'wánzhěng'], ['fān・yì', 'fānyì'], ['fān//yì', 'fānyì'], + ['fān’yì', 'fānyì'], + ['fān\'yì', 'fānyì'], + ['fān-yì', 'fānyì'], ]; describe('Normalize Pinyin', () => { diff --git a/test/language/japanese-transforms.test.js b/test/language/japanese-transforms.test.js index 2ae622c4a6..817f59c4cc 100644 --- a/test/language/japanese-transforms.test.js +++ b/test/language/japanese-transforms.test.js @@ -1366,6 +1366,7 @@ const tests = [ {term: 'とう', source: 'とうて', rule: 'v5', reasons: ['-て']}, {term: '請う', source: '請うて', rule: 'v5', reasons: ['-て']}, {term: '乞う', source: '乞うて', rule: 'v5', reasons: ['-て']}, + {term: '恋う', source: '恋うて', rule: 'v5', reasons: ['-て']}, {term: '問う', source: '問うて', rule: 'v5', reasons: ['-て']}, {term: '訪う', source: '訪うて', rule: 'v5', reasons: ['-て']}, @@ -1373,6 +1374,7 @@ const tests = [ {term: 'とう', source: 'とうた', rule: 'v5', reasons: ['-た']}, {term: '請う', source: '請うた', rule: 'v5', reasons: ['-た']}, {term: '乞う', source: '乞うた', rule: 'v5', reasons: ['-た']}, + {term: '恋う', source: '恋うた', rule: 'v5', reasons: ['-た']}, {term: '問う', source: '問うた', rule: 'v5', reasons: ['-た']}, {term: '訪う', source: '訪うた', rule: 'v5', reasons: ['-た']}, @@ -1380,6 +1382,7 @@ const tests = [ {term: 'とう', source: 'とうたら', rule: 'v5', reasons: ['-たら']}, {term: '請う', source: '請うたら', rule: 'v5', reasons: ['-たら']}, {term: '乞う', source: '乞うたら', rule: 'v5', reasons: ['-たら']}, + {term: '恋う', source: '恋うたら', rule: 'v5', reasons: ['-たら']}, {term: '問う', source: '問うたら', rule: 'v5', reasons: ['-たら']}, {term: '訪う', source: '訪うたら', rule: 'v5', reasons: ['-たら']}, @@ -1387,6 +1390,7 @@ const tests = [ {term: 'とう', source: 'とうたり', rule: 'v5', reasons: ['-たり']}, {term: '請う', source: '請うたり', rule: 'v5', reasons: ['-たり']}, {term: '乞う', source: '乞うたり', rule: 'v5', reasons: ['-たり']}, + {term: '恋う', source: '恋うたり', rule: 'v5', reasons: ['-たり']}, {term: '問う', source: '問うたり', rule: 'v5', reasons: ['-たり']}, {term: '訪う', source: '訪うたり', rule: 'v5', reasons: ['-たり']}, ], diff --git a/test/playwright/visual.spec.js b/test/playwright/visual.spec.js index 5cdf3582f1..430dbdf118 100644 --- a/test/playwright/visual.spec.js +++ b/test/playwright/visual.spec.js @@ -26,6 +26,13 @@ test.beforeEach(async ({context}) => { }); test('visual', async ({page, extensionId}) => { + // Open welcome page + await page.goto(`chrome-extension://${extensionId}/welcome.html`); + await expect(page.getByText('Welcome to Yomitan!')).toBeVisible(); + + // Take a screenshot of the welcome page + await expect.soft(page).toHaveScreenshot('welcome-page.png'); + // Open settings await page.goto(`chrome-extension://${extensionId}/settings.html`);