AnkiUtil (#1439)
* Add AnkiUtil * Update AnkiConnect to use AnkiUtil * Use AnkiUtil in AnkiNoteBuilder * Replace containsAnyMarker with AnkiUtil.stringContainsAnyFieldMarker * Add AnkiUtil.getFieldMarkers * Add fieldsObjectContainsMarker to AnkiUtil * Remove unused global * Remove unused parameter: enabled * Add cloneFieldMarkerPattern
This commit is contained in:
parent
0a76de1b44
commit
ae92e0b378
@ -178,6 +178,7 @@
|
|||||||
"ext/js/comm/clipboard-monitor.js",
|
"ext/js/comm/clipboard-monitor.js",
|
||||||
"ext/js/comm/clipboard-reader.js",
|
"ext/js/comm/clipboard-reader.js",
|
||||||
"ext/js/comm/mecab.js",
|
"ext/js/comm/mecab.js",
|
||||||
|
"ext/js/data/anki-util.js",
|
||||||
"ext/js/data/database.js",
|
"ext/js/data/database.js",
|
||||||
"ext/js/data/json-schema.js",
|
"ext/js/data/json-schema.js",
|
||||||
"ext/js/data/options-util.js",
|
"ext/js/data/options-util.js",
|
||||||
|
@ -88,6 +88,7 @@
|
|||||||
|
|
||||||
<script src="/js/comm/api.js"></script>
|
<script src="/js/comm/api.js"></script>
|
||||||
<script src="/js/comm/cross-frame-api.js"></script>
|
<script src="/js/comm/cross-frame-api.js"></script>
|
||||||
|
<script src="/js/data/anki-util.js"></script>
|
||||||
<script src="/js/data/permissions-util.js"></script>
|
<script src="/js/data/permissions-util.js"></script>
|
||||||
<script src="/js/input/hotkey-help-controller.js"></script>
|
<script src="/js/input/hotkey-help-controller.js"></script>
|
||||||
<script src="/js/input/hotkey-util.js"></script>
|
<script src="/js/input/hotkey-util.js"></script>
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
<script src="/js/comm/clipboard-monitor.js"></script>
|
<script src="/js/comm/clipboard-monitor.js"></script>
|
||||||
<script src="/js/comm/clipboard-reader.js"></script>
|
<script src="/js/comm/clipboard-reader.js"></script>
|
||||||
<script src="/js/comm/mecab.js"></script>
|
<script src="/js/comm/mecab.js"></script>
|
||||||
|
<script src="/js/data/anki-util.js"></script>
|
||||||
<script src="/js/data/database.js"></script>
|
<script src="/js/data/database.js"></script>
|
||||||
<script src="/js/data/json-schema.js"></script>
|
<script src="/js/data/json-schema.js"></script>
|
||||||
<script src="/js/data/options-util.js"></script>
|
<script src="/js/data/options-util.js"></script>
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
|
|
||||||
<script src="/js/comm/api.js"></script>
|
<script src="/js/comm/api.js"></script>
|
||||||
<script src="/js/comm/cross-frame-api.js"></script>
|
<script src="/js/comm/cross-frame-api.js"></script>
|
||||||
|
<script src="/js/data/anki-util.js"></script>
|
||||||
<script src="/js/data/permissions-util.js"></script>
|
<script src="/js/data/permissions-util.js"></script>
|
||||||
<script src="/js/dom/document-focus-controller.js"></script>
|
<script src="/js/dom/document-focus-controller.js"></script>
|
||||||
<script src="/js/dom/html-template-collection.js"></script>
|
<script src="/js/dom/html-template-collection.js"></script>
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* global
|
||||||
|
* AnkiUtil
|
||||||
|
*/
|
||||||
|
|
||||||
class AnkiConnect {
|
class AnkiConnect {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._enabled = false;
|
this._enabled = false;
|
||||||
@ -113,7 +117,7 @@ class AnkiConnect {
|
|||||||
query = `"deck:${this._escapeQuery(note.deckName)}" `;
|
query = `"deck:${this._escapeQuery(note.deckName)}" `;
|
||||||
break;
|
break;
|
||||||
case 'deck-root':
|
case 'deck-root':
|
||||||
query = `"deck:${this._escapeQuery(this.getRootDeckName(note.deckName))}" `;
|
query = `"deck:${this._escapeQuery(AnkiUtil.getRootDeckName(note.deckName))}" `;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
query += this._fieldsToQuery(note.fields);
|
query += this._fieldsToQuery(note.fields);
|
||||||
@ -138,11 +142,6 @@ class AnkiConnect {
|
|||||||
return await this.findCards(`nid:${noteId}`);
|
return await this.findCards(`nid:${noteId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRootDeckName(deckName) {
|
|
||||||
const index = deckName.indexOf('::');
|
|
||||||
return index >= 0 ? deckName.substring(0, index) : deckName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
|
|
||||||
async _checkVersion() {
|
async _checkVersion() {
|
||||||
|
@ -16,13 +16,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
|
* AnkiUtil
|
||||||
* TemplateRendererProxy
|
* TemplateRendererProxy
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class AnkiNoteBuilder {
|
class AnkiNoteBuilder {
|
||||||
constructor(enabled) {
|
constructor() {
|
||||||
this._markerPattern = /\{([\w-]+)\}/g;
|
this._markerPattern = AnkiUtil.cloneFieldMarkerPattern(true);
|
||||||
this._templateRenderer = enabled ? new TemplateRendererProxy() : null;
|
this._templateRenderer = new TemplateRendererProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNote({
|
async createNote({
|
||||||
@ -46,7 +47,7 @@ class AnkiNoteBuilder {
|
|||||||
let duplicateScopeCheckChildren = false;
|
let duplicateScopeCheckChildren = false;
|
||||||
if (duplicateScope === 'deck-root') {
|
if (duplicateScope === 'deck-root') {
|
||||||
duplicateScope = 'deck';
|
duplicateScope = 'deck';
|
||||||
duplicateScopeDeckName = this.getRootDeckName(deckName);
|
duplicateScopeDeckName = AnkiUtil.getRootDeckName(deckName);
|
||||||
duplicateScopeCheckChildren = true;
|
duplicateScopeCheckChildren = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,27 +90,6 @@ class AnkiNoteBuilder {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
containsMarker(fields, marker) {
|
|
||||||
marker = `{${marker}}`;
|
|
||||||
for (const [, fieldValue] of fields) {
|
|
||||||
if (fieldValue.includes(marker)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
containsAnyMarker(field) {
|
|
||||||
const result = this._markerPattern.test(field);
|
|
||||||
this._markerPattern.lastIndex = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
getRootDeckName(deckName) {
|
|
||||||
const index = deckName.indexOf('::');
|
|
||||||
return index >= 0 ? deckName.substring(0, index) : deckName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
|
|
||||||
async _formatField(field, data, templates, errors=null) {
|
async _formatField(field, data, templates, errors=null) {
|
||||||
|
87
ext/js/data/anki-util.js
Normal file
87
ext/js/data/anki-util.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Yomichan Authors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class has some general utility functions for working with Anki data.
|
||||||
|
*/
|
||||||
|
class AnkiUtil {
|
||||||
|
/**
|
||||||
|
* Gets the root deck name of a full deck name. If the deck is a root deck,
|
||||||
|
* the same name is returned. Nested decks are separated using '::'.
|
||||||
|
* @param deckName A string of the deck name.
|
||||||
|
* @returns A string corresponding to the name of the root deck.
|
||||||
|
*/
|
||||||
|
static getRootDeckName(deckName) {
|
||||||
|
const index = deckName.indexOf('::');
|
||||||
|
return index >= 0 ? deckName.substring(0, index) : deckName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether or not any marker is contained in a string.
|
||||||
|
* @param string A string to check.
|
||||||
|
* @return `true` if the text contains an Anki field marker, `false` otherwise.
|
||||||
|
*/
|
||||||
|
static stringContainsAnyFieldMarker(string) {
|
||||||
|
const result = this._markerPattern.test(string);
|
||||||
|
this._markerPattern.lastIndex = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of all markers that are contained in a string.
|
||||||
|
* @param string A string to check.
|
||||||
|
* @return An array of marker strings.
|
||||||
|
*/
|
||||||
|
static getFieldMarkers(string) {
|
||||||
|
const pattern = this._markerPattern;
|
||||||
|
const markers = [];
|
||||||
|
while (true) {
|
||||||
|
const match = pattern.exec(string);
|
||||||
|
if (match === null) { break; }
|
||||||
|
markers.push(match[1]);
|
||||||
|
}
|
||||||
|
return markers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether an object of key-value pairs has a value which contains a specific marker.
|
||||||
|
* @param fieldsObject An object with key-value pairs, where the value corresponds to the field value.
|
||||||
|
* @param marker The marker string to check for, excluding brackets.
|
||||||
|
* @returns `true` if any of the fields contains the marker, `false` otherwise.
|
||||||
|
*/
|
||||||
|
static fieldsObjectContainsMarker(fieldsObject, marker) {
|
||||||
|
marker = `{${marker}}`;
|
||||||
|
for (const [, fieldValue] of fieldsObject) {
|
||||||
|
if (fieldValue.includes(marker)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a regular expression which can be used to find markers in a string.
|
||||||
|
* @param global Whether or not the regular expression should have the global flag.
|
||||||
|
* @returns A new `RegExp` instance.
|
||||||
|
*/
|
||||||
|
static cloneFieldMarkerPattern(global) {
|
||||||
|
return new RegExp(this._markerPattern.source, global ? 'g' : '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
AnkiUtil._markerPattern = /\{([\w-]+)\}/g;
|
@ -15,13 +15,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* global
|
||||||
|
* AnkiUtil
|
||||||
|
*/
|
||||||
|
|
||||||
class PermissionsUtil {
|
class PermissionsUtil {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._ankiFieldMarkersRequiringClipboardPermission = new Set([
|
this._ankiFieldMarkersRequiringClipboardPermission = new Set([
|
||||||
'clipboard-image',
|
'clipboard-image',
|
||||||
'clipboard-text'
|
'clipboard-text'
|
||||||
]);
|
]);
|
||||||
this._ankiMarkerPattern = /\{([\w-]+)\}/g;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasPermissions(permissions) {
|
hasPermissions(permissions) {
|
||||||
@ -69,7 +72,7 @@ class PermissionsUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRequiredPermissionsForAnkiFieldValue(fieldValue) {
|
getRequiredPermissionsForAnkiFieldValue(fieldValue) {
|
||||||
const markers = this._getAnkiFieldMarkers(fieldValue);
|
const markers = AnkiUtil.getFieldMarkers(fieldValue);
|
||||||
const markerPermissions = this._ankiFieldMarkersRequiringClipboardPermission;
|
const markerPermissions = this._ankiFieldMarkersRequiringClipboardPermission;
|
||||||
for (const marker of markers) {
|
for (const marker of markers) {
|
||||||
if (markerPermissions.has(marker)) {
|
if (markerPermissions.has(marker)) {
|
||||||
@ -99,7 +102,7 @@ class PermissionsUtil {
|
|||||||
];
|
];
|
||||||
for (const fields of fieldsList) {
|
for (const fields of fieldsList) {
|
||||||
for (const fieldValue of Object.values(fields)) {
|
for (const fieldValue of Object.values(fields)) {
|
||||||
const markers = this._getAnkiFieldMarkers(fieldValue);
|
const markers = AnkiUtil.getFieldMarkers(fieldValue);
|
||||||
for (const marker of markers) {
|
for (const marker of markers) {
|
||||||
if (fieldMarkersRequiringClipboardPermission.has(marker)) {
|
if (fieldMarkersRequiringClipboardPermission.has(marker)) {
|
||||||
return false;
|
return false;
|
||||||
@ -111,16 +114,4 @@ class PermissionsUtil {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
|
||||||
|
|
||||||
_getAnkiFieldMarkers(fieldValue) {
|
|
||||||
const pattern = this._ankiMarkerPattern;
|
|
||||||
const markers = [];
|
|
||||||
let match;
|
|
||||||
while ((match = pattern.exec(fieldValue)) !== null) {
|
|
||||||
markers.push(match[1]);
|
|
||||||
}
|
|
||||||
return markers;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
/* global
|
/* global
|
||||||
* AnkiNoteBuilder
|
* AnkiNoteBuilder
|
||||||
|
* AnkiUtil
|
||||||
* DisplayAudio
|
* DisplayAudio
|
||||||
* DisplayGenerator
|
* DisplayGenerator
|
||||||
* DisplayHistory
|
* DisplayHistory
|
||||||
@ -85,7 +86,7 @@ class Display extends EventDispatcher {
|
|||||||
});
|
});
|
||||||
this._ankiFieldTemplates = null;
|
this._ankiFieldTemplates = null;
|
||||||
this._ankiFieldTemplatesDefault = null;
|
this._ankiFieldTemplatesDefault = null;
|
||||||
this._ankiNoteBuilder = new AnkiNoteBuilder(true);
|
this._ankiNoteBuilder = new AnkiNoteBuilder();
|
||||||
this._updateAdderButtonsPromise = Promise.resolve();
|
this._updateAdderButtonsPromise = Promise.resolve();
|
||||||
this._contentScrollElement = document.querySelector('#content-scroll');
|
this._contentScrollElement = document.querySelector('#content-scroll');
|
||||||
this._contentScrollBodyElement = document.querySelector('#content-body');
|
this._contentScrollBodyElement = document.querySelector('#content-body');
|
||||||
@ -1493,7 +1494,7 @@ class Display extends EventDispatcher {
|
|||||||
const definitionDetails = this._getDefinitionDetailsForNote(definition);
|
const definitionDetails = this._getDefinitionDetailsForNote(definition);
|
||||||
|
|
||||||
let audioDetails = null;
|
let audioDetails = null;
|
||||||
if (definitionDetails.type !== 'kanji' && this._ankiNoteBuilder.containsMarker(fields, 'audio')) {
|
if (definitionDetails.type !== 'kanji' && AnkiUtil.fieldsObjectContainsMarker(fields, 'audio')) {
|
||||||
const primaryCardAudio = this._displayAudio.getPrimaryCardAudio(definitionDetails.expression, definitionDetails.reading);
|
const primaryCardAudio = this._displayAudio.getPrimaryCardAudio(definitionDetails.expression, definitionDetails.reading);
|
||||||
let preferredAudioIndex = null;
|
let preferredAudioIndex = null;
|
||||||
let sources2 = sources;
|
let sources2 = sources;
|
||||||
@ -1504,11 +1505,11 @@ class Display extends EventDispatcher {
|
|||||||
audioDetails = {sources: sources2, preferredAudioIndex, customSourceUrl, customSourceType};
|
audioDetails = {sources: sources2, preferredAudioIndex, customSourceUrl, customSourceType};
|
||||||
}
|
}
|
||||||
|
|
||||||
const screenshotDetails = (this._ankiNoteBuilder.containsMarker(fields, 'screenshot') ? {tabId: this._contentOriginTabId, frameId: this._contentOriginFrameId, format, quality} : null);
|
const screenshotDetails = (AnkiUtil.fieldsObjectContainsMarker(fields, 'screenshot') ? {tabId: this._contentOriginTabId, frameId: this._contentOriginFrameId, format, quality} : null);
|
||||||
|
|
||||||
const clipboardDetails = {
|
const clipboardDetails = {
|
||||||
image: this._ankiNoteBuilder.containsMarker(fields, 'clipboard-image'),
|
image: AnkiUtil.fieldsObjectContainsMarker(fields, 'clipboard-image'),
|
||||||
text: this._ankiNoteBuilder.containsMarker(fields, 'clipboard-text')
|
text: AnkiUtil.fieldsObjectContainsMarker(fields, 'clipboard-text')
|
||||||
};
|
};
|
||||||
|
|
||||||
return await yomichan.api.injectAnkiNoteMedia(
|
return await yomichan.api.injectAnkiNoteMedia(
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
/* global
|
/* global
|
||||||
* AnkiConnect
|
* AnkiConnect
|
||||||
* AnkiNoteBuilder
|
* AnkiUtil
|
||||||
* ObjectPropertyAccessor
|
* ObjectPropertyAccessor
|
||||||
* SelectorObserver
|
* SelectorObserver
|
||||||
*/
|
*/
|
||||||
@ -26,7 +26,6 @@ class AnkiController {
|
|||||||
constructor(settingsController) {
|
constructor(settingsController) {
|
||||||
this._settingsController = settingsController;
|
this._settingsController = settingsController;
|
||||||
this._ankiConnect = new AnkiConnect();
|
this._ankiConnect = new AnkiConnect();
|
||||||
this._ankiNoteBuilder = new AnkiNoteBuilder(false);
|
|
||||||
this._selectorObserver = new SelectorObserver({
|
this._selectorObserver = new SelectorObserver({
|
||||||
selector: '.anki-card',
|
selector: '.anki-card',
|
||||||
ignoreSelector: null,
|
ignoreSelector: null,
|
||||||
@ -156,10 +155,6 @@ class AnkiController {
|
|||||||
return this._settingsController.permissionsUtil.getRequiredPermissionsForAnkiFieldValue(fieldValue);
|
return this._settingsController.permissionsUtil.getRequiredPermissionsForAnkiFieldValue(fieldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
containsAnyMarker(field) {
|
|
||||||
return this._ankiNoteBuilder.containsAnyMarker(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
|
|
||||||
async _onOptionsChanged({options: {anki}}) {
|
async _onOptionsChanged({options: {anki}}) {
|
||||||
@ -439,7 +434,7 @@ class AnkiCardController {
|
|||||||
|
|
||||||
_validateField(node, index) {
|
_validateField(node, index) {
|
||||||
let valid = (node.dataset.hasPermissions !== 'false');
|
let valid = (node.dataset.hasPermissions !== 'false');
|
||||||
if (valid && index === 0 && !this._ankiController.containsAnyMarker(node.value)) {
|
if (valid && index === 0 && !AnkiUtil.stringContainsAnyFieldMarker(node.value)) {
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
node.dataset.invalid = `${!valid}`;
|
node.dataset.invalid = `${!valid}`;
|
||||||
|
@ -32,7 +32,7 @@ class AnkiTemplatesController {
|
|||||||
this._renderFieldInput = null;
|
this._renderFieldInput = null;
|
||||||
this._renderResult = null;
|
this._renderResult = null;
|
||||||
this._fieldTemplateResetModal = null;
|
this._fieldTemplateResetModal = null;
|
||||||
this._ankiNoteBuilder = new AnkiNoteBuilder(true);
|
this._ankiNoteBuilder = new AnkiNoteBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepare() {
|
async prepare() {
|
||||||
|
@ -167,6 +167,7 @@
|
|||||||
|
|
||||||
<script src="/js/comm/api.js"></script>
|
<script src="/js/comm/api.js"></script>
|
||||||
<script src="/js/comm/cross-frame-api.js"></script>
|
<script src="/js/comm/cross-frame-api.js"></script>
|
||||||
|
<script src="/js/data/anki-util.js"></script>
|
||||||
<script src="/js/data/permissions-util.js"></script>
|
<script src="/js/data/permissions-util.js"></script>
|
||||||
<script src="/js/dom/document-focus-controller.js"></script>
|
<script src="/js/dom/document-focus-controller.js"></script>
|
||||||
<script src="/js/dom/html-template-collection.js"></script>
|
<script src="/js/dom/html-template-collection.js"></script>
|
||||||
|
@ -97,6 +97,7 @@
|
|||||||
<script src="/js/comm/cross-frame-api.js"></script>
|
<script src="/js/comm/cross-frame-api.js"></script>
|
||||||
<script src="/js/comm/frame-endpoint.js"></script>
|
<script src="/js/comm/frame-endpoint.js"></script>
|
||||||
<script src="/js/data/anki-note-builder.js"></script>
|
<script src="/js/data/anki-note-builder.js"></script>
|
||||||
|
<script src="/js/data/anki-util.js"></script>
|
||||||
<script src="/js/display/display.js"></script>
|
<script src="/js/display/display.js"></script>
|
||||||
<script src="/js/display/display-audio.js"></script>
|
<script src="/js/display/display-audio.js"></script>
|
||||||
<script src="/js/display/display-generator.js"></script>
|
<script src="/js/display/display-generator.js"></script>
|
||||||
|
@ -83,6 +83,7 @@
|
|||||||
<script src="/js/comm/clipboard-monitor.js"></script>
|
<script src="/js/comm/clipboard-monitor.js"></script>
|
||||||
<script src="/js/comm/cross-frame-api.js"></script>
|
<script src="/js/comm/cross-frame-api.js"></script>
|
||||||
<script src="/js/data/anki-note-builder.js"></script>
|
<script src="/js/data/anki-note-builder.js"></script>
|
||||||
|
<script src="/js/data/anki-util.js"></script>
|
||||||
<script src="/js/display/display.js"></script>
|
<script src="/js/display/display.js"></script>
|
||||||
<script src="/js/display/display-audio.js"></script>
|
<script src="/js/display/display-audio.js"></script>
|
||||||
<script src="/js/display/display-generator.js"></script>
|
<script src="/js/display/display-generator.js"></script>
|
||||||
|
@ -1288,6 +1288,7 @@
|
|||||||
<script src="/js/comm/api.js"></script>
|
<script src="/js/comm/api.js"></script>
|
||||||
<script src="/js/comm/cross-frame-api.js"></script>
|
<script src="/js/comm/cross-frame-api.js"></script>
|
||||||
<script src="/js/data/anki-note-builder.js"></script>
|
<script src="/js/data/anki-note-builder.js"></script>
|
||||||
|
<script src="/js/data/anki-util.js"></script>
|
||||||
<script src="/js/data/database.js"></script>
|
<script src="/js/data/database.js"></script>
|
||||||
<script src="/js/data/json-schema.js"></script>
|
<script src="/js/data/json-schema.js"></script>
|
||||||
<script src="/js/data/options-util.js"></script>
|
<script src="/js/data/options-util.js"></script>
|
||||||
|
@ -3198,6 +3198,7 @@
|
|||||||
<script src="/js/comm/api.js"></script>
|
<script src="/js/comm/api.js"></script>
|
||||||
<script src="/js/comm/cross-frame-api.js"></script>
|
<script src="/js/comm/cross-frame-api.js"></script>
|
||||||
<script src="/js/data/anki-note-builder.js"></script>
|
<script src="/js/data/anki-note-builder.js"></script>
|
||||||
|
<script src="/js/data/anki-util.js"></script>
|
||||||
<script src="/js/data/database.js"></script>
|
<script src="/js/data/database.js"></script>
|
||||||
<script src="/js/data/json-schema.js"></script>
|
<script src="/js/data/json-schema.js"></script>
|
||||||
<script src="/js/data/options-util.js"></script>
|
<script src="/js/data/options-util.js"></script>
|
||||||
|
@ -28,6 +28,7 @@ self.importScripts(
|
|||||||
'/js/comm/clipboard-monitor.js',
|
'/js/comm/clipboard-monitor.js',
|
||||||
'/js/comm/clipboard-reader.js',
|
'/js/comm/clipboard-reader.js',
|
||||||
'/js/comm/mecab.js',
|
'/js/comm/mecab.js',
|
||||||
|
'/js/data/anki-util.js',
|
||||||
'/js/data/database.js',
|
'/js/data/database.js',
|
||||||
'/js/data/json-schema.js',
|
'/js/data/json-schema.js',
|
||||||
'/js/data/options-util.js',
|
'/js/data/options-util.js',
|
||||||
|
@ -320,6 +320,7 @@
|
|||||||
|
|
||||||
<script src="/js/comm/api.js"></script>
|
<script src="/js/comm/api.js"></script>
|
||||||
<script src="/js/comm/cross-frame-api.js"></script>
|
<script src="/js/comm/cross-frame-api.js"></script>
|
||||||
|
<script src="/js/data/anki-util.js"></script>
|
||||||
<script src="/js/data/database.js"></script>
|
<script src="/js/data/database.js"></script>
|
||||||
<script src="/js/data/json-schema.js"></script>
|
<script src="/js/data/json-schema.js"></script>
|
||||||
<script src="/js/data/permissions-util.js"></script>
|
<script src="/js/data/permissions-util.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user