diff options
Diffstat (limited to 'ext/bg/js/mecab.js')
-rw-r--r-- | ext/bg/js/mecab.js | 230 |
1 files changed, 0 insertions, 230 deletions
diff --git a/ext/bg/js/mecab.js b/ext/bg/js/mecab.js deleted file mode 100644 index 4eff2927..00000000 --- a/ext/bg/js/mecab.js +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2019-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 is used to connect Yomichan to a native component that is - * used to parse text into individual terms. - */ -class Mecab { - /** - * Creates a new instance of the class. - */ - constructor() { - this._port = null; - this._sequence = 0; - this._invocations = new Map(); - this._eventListeners = new EventListenerCollection(); - this._timeout = 5000; - this._version = 1; - this._remoteVersion = null; - this._enabled = false; - this._setupPortPromise = null; - } - - /** - * Returns whether or not the component is enabled. - */ - isEnabled() { - return this._enabled; - } - - /** - * Changes whether or not the component connection is enabled. - * @param enabled A boolean indicating whether or not the component should be enabled. - */ - setEnabled(enabled) { - this._enabled = !!enabled; - if (!this._enabled && this._port !== null) { - this._clearPort(); - } - } - - /** - * Disconnects the current port, but does not disable future connections. - */ - disconnect() { - if (this._port !== null) { - this._clearPort(); - } - } - - /** - * Returns whether or not the connection to the native application is active. - * @returns `true` if the connection is active, `false` otherwise. - */ - isConnected() { - return (this._port !== null); - } - - /** - * Returns whether or not any invocation is currently active. - * @returns `true` if an invocation is active, `false` otherwise. - */ - isActive() { - return (this._invocations.size > 0); - } - - /** - * Gets the local API version being used. - * @returns An integer representing the API version that Yomichan uses. - */ - getLocalVersion() { - return this._version; - } - - /** - * Gets the version of the MeCab component. - * @returns The version of the MeCab component, or `null` if the component was not found. - */ - async getVersion() { - try { - await this._setupPort(); - } catch (e) { - // NOP - } - return this._remoteVersion; - } - - /** - * Parses a string of Japanese text into arrays of lines and terms. - * - * Return value format: - * ```js - * [ - * { - * name: (string), - * lines: [ - * {expression: (string), reading: (string), source: (string)}, - * ... - * ] - * }, - * ... - * ] - * ``` - * @param text The string to parse. - * @returns A collection of parsing results of the text. - */ - async parseText(text) { - await this._setupPort(); - const rawResults = await this._invoke('parse_text', {text}); - return this._convertParseTextResults(rawResults); - } - - // Private - - _onMessage({sequence, data}) { - const invocation = this._invocations.get(sequence); - if (typeof invocation === 'undefined') { return; } - - const {resolve, timer} = invocation; - clearTimeout(timer); - resolve(data); - this._invocations.delete(sequence); - } - - _onDisconnect() { - if (this._port === null) { return; } - const e = chrome.runtime.lastError; - const error = new Error(e ? e.message : 'MeCab disconnected'); - for (const {reject, timer} of this._invocations.values()) { - clearTimeout(timer); - reject(error); - } - this._clearPort(); - } - - _invoke(action, params) { - return new Promise((resolve, reject) => { - if (this._port === null) { - reject(new Error('Port disconnected')); - } - - const sequence = this._sequence++; - - const timer = setTimeout(() => { - this._invocations.delete(sequence); - reject(new Error(`MeCab invoke timed out after ${this._timeout}ms`)); - }, this._timeout); - - this._invocations.set(sequence, {resolve, reject, timer}, this._timeout); - - this._port.postMessage({action, params, sequence}); - }); - } - - _convertParseTextResults(rawResults) { - const results = []; - for (const [name, rawLines] of Object.entries(rawResults)) { - const lines = []; - for (const rawLine of rawLines) { - const line = []; - for (let {expression, reading, source} of rawLine) { - if (typeof expression !== 'string') { expression = ''; } - if (typeof reading !== 'string') { reading = ''; } - if (typeof source !== 'string') { source = ''; } - line.push({expression, reading, source}); - } - lines.push(line); - } - results.push({name, lines}); - } - return results; - } - - async _setupPort() { - if (!this._enabled) { - throw new Error('MeCab not enabled'); - } - if (this._setupPortPromise === null) { - this._setupPortPromise = this._setupPort2(); - } - try { - await this._setupPortPromise; - } catch (e) { - throw new Error(e.message); - } - } - - async _setupPort2() { - const port = chrome.runtime.connectNative('yomichan_mecab'); - this._eventListeners.addListener(port.onMessage, this._onMessage.bind(this)); - this._eventListeners.addListener(port.onDisconnect, this._onDisconnect.bind(this)); - this._port = port; - - try { - const {version} = await this._invoke('get_version', {}); - this._remoteVersion = version; - if (version !== this._version) { - throw new Error(`Unsupported MeCab native messenger version ${version}. Yomichan supports version ${this._version}.`); - } - } catch (e) { - if (this._port === port) { - this._clearPort(); - } - throw e; - } - } - - _clearPort() { - this._port.disconnect(); - this._port = null; - this._invocations.clear(); - this._eventListeners.removeAllEventListeners(); - this._sequence = 0; - this._setupPortPromise = null; - } -} |