Greasy Fork

来自缓存

Greasy Fork is available in English.

ユーティリティクラス

HTML、XML、DOM、文字列に関する汎用的な処理をまとめたライブラリです。

当前为 2016-08-05 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/19616/140111/%E3%83%A6%E3%83%BC%E3%83%86%E3%82%A3%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AF%E3%83%A9%E3%82%B9.js

// ==UserScript==
// @name        ユーティリティクラス
// @version     1.2.0
// @description HTML、XML、DOM、文字列に関する汎用的な処理をまとめたライブラリです。
// @license     Mozilla Public License Version 2.0 (MPL 2.0); https://www.mozilla.org/MPL/2.0/
// @compatible  Firefox
// @compatible  Opera
// @compatible  Chrome
// @author      100の人
// @homepage    http://greasyfork.icu/scripts/19616
// ==/UserScript==

(function () {
'use strict';

/**
 * HTML、XML、DOMに関するメソッド等。
 */
window.MarkupUtils = {
	/**
	 * Atom名前空間。
	 * @constant {string}
	 */
	ATOM_NAMESPACE: 'http://www.w3.org/2005/Atom',

	/**
	 * XMLの特殊文字と文字参照の変換テーブル。
	 * @constant {Object.<string>}
	 */
	CHARACTER_REFERENCES_TRANSLATION_TABLE: {
		'&': '&amp;',
		'<': '&lt;',
		'>': '&gt;',
		'"': '&quot;',
		"'": '&apos;',
	},

	/**
	 * XMLの特殊文字を文字参照に置換します。
	 * @see [html - HtmlSpecialChars equivalent in Javascript? - Stack Overflow]{@link http://stackoverflow.com/a/4835406}
	 * @param {string} str - プレーンな文字列。
	 * @returns {string} HTMLとして扱われる文字列。
	 */
	convertSpecialCharactersToCharacterReferences(str) {
		return String(str).replace(
			/[&<>"']/g,
			specialCharcter => this.CHARACTER_REFERENCES_TRANSLATION_TABLE[specialCharcter]
		);
	},

	/**
	 * テンプレート文字列のタグとして用いることで、式内にあるXMLの特殊文字を文字参照に置換します。
	 * @param {string[]} htmlTexts
	 * @param {...string} plainText
	 * @returns {string} HTMLとして扱われる文字列。
	 */
	escapeTemplateStrings(htmlTexts, ...plainTexts) {
		return String.raw(
			htmlTexts,
			...plainTexts.map(plainText => this.convertSpecialCharactersToCharacterReferences(plainText))
		);
	},

	/**
	 * 指定したURLからファイルをダウンロードします。
	 * @param {string} url
	 * @param {string} filename
	 */
	download(url, filename) {
		let body = document.body;
		body.insertAdjacentHTML('beforeend', h`<a href="${url}" download="${filename}" hidden=""></a>`);
		let anchor = body.lastElementChild;
		anchor.click();
		anchor.remove();
	},
};

/**
 * {@link MarkupUtils.escapeTemplateStrings}、または {@link MarkupUtils.convertSpecialCharactersToCharacterReferences} の短縮表記。
 * @example
 * // returns "<code>&lt;a href=&quot;https://example.com/&quot;link text&lt;/a&gt;</code>"
 * h`<code>${'<a href="https://example.com/">link text</a>'}</code>`;
 * @example
 * // returns "&lt;a href=&quot;https://example.com/&quot;link text&lt;/a&gt;"
 * h('<a href="https://example.com/">link text</a>');
 * @returns {string}
 */
window.h = function () {
	return Array.isArray(arguments[0])
		? MarkupUtils.escapeTemplateStrings(...arguments)
		: MarkupUtils.convertSpecialCharactersToCharacterReferences(arguments[0]);
};

/**
 * 文字、文字列の処理を行うメソッド等。
 */
window.StringProcessor = {
	/**
	 * ひらがなをカタカナに変換するときの加数。
	 * @constant {number}
	 */
	ADDEND_HIRAGANA_TO_KATAKANA: 'ァ'.charCodeAt() - 'ぁ'.charCodeAt(),

	/**
	 * ひらがなをカタカナに変換します。
	 * @param {string} str
	 * @returns {string}
	 */
	convertToKatakana(str) {
		return str.replace(
			/[ぁ-ゖ]/g,
			match => String.fromCharCode(match.charCodeAt() + this.ADDEND_HIRAGANA_TO_KATAKANA)
		);
	},
};

/**
 * 以下のような形式の翻訳リソース。すべての言語について、msgidは欠けていないものとする。
 * {@link Gettext.DEFAULT_LOCALE}のリソースを必ず含む。{@link Gettext.ORIGINAL_LOCALE}のリソースは無視される。
 * {
 *     'IETF言語タグ': {
 *         '翻訳前 (msgid)': '翻訳後 (msgstr)',
 *         ……
 *     },
 *     ……
 * }
 * @typedef {Object} LocalizedTexts
 */

/**
 * i18n。
 */
window.Gettext = class {
	/**
	 * 翻訳対象文字列 (msgid) の言語。IETF言語タグの「language」サブタグ。
	 * @constant {string}
	 */
	static get ORIGINAL_LOCALE() {return 'ja';}

	/**
	 * クライアントの言語の翻訳リソースが存在しないとき、どの言語に翻訳するか。IETF言語タグの「language」サブタグ。
	 * @constant {string}
	 */
	static get DEFAULT_LOCALE() {return 'en';}

	/**
	 * 翻訳リソースを追加します。
	 * @param {LocalizedTexts} localizedTexts
	 */
	static setLocalizedTexts(localizedTexts)
	{
		this.multilingualLocalizedTexts = localizedTexts;
	}

	/**
	 * クライアントの言語を設定します。
	 * @param {string} clientLang - IETF言語タグ (「language」と「language-REGION」にのみ対応)。
	 */
	static setLocale(clientLang)
	{
		let splitedClientLang = clientLang.split('-', 2);
		this.language = splitedClientLang[0].toLowerCase();
		this.langtag = this.language + (splitedClientLang[1] ? '-' + splitedClientLang[1].toUpperCase() : '');
		if (this.language === 'ja') {
			// ja-JPをjaと同一視
			this.langtag = this.language;
		}
	}

	/**
	 * テキストをクライアントの言語に変換します。
	 * @param {string} message - 翻訳前。
	 * @returns {string} 翻訳後。
	 */
	static gettext(message)
	{
		// クライアントの言語が翻訳元の言語なら、そのまま返す
		return this.langtag === this.ORIGINAL_LOCALE && message
				// クライアントの言語の翻訳リソースが存在すれば、それを返す
				|| this.langtag in this.multilingualLocalizedTexts && this.multilingualLocalizedTexts[this.langtag][message]
				// 地域下位タグを取り除いた言語タグの翻訳リソースが存在すれば、それを返す
				|| this.language in this.multilingualLocalizedTexts && this.multilingualLocalizedTexts[this.language][message]
				// 既定言語の翻訳リソースが存在すれば、それを返す
				|| this.DEFAULT_LOCALE in this.multilingualLocalizedTexts && this.multilingualLocalizedTexts[this.DEFAULT_LOCALE][message]
				// そのまま返す
				|| message;
	}
};

/**
 * クライアントの言語。{@link Gettext.setLocale}から変更されます。
 * @access private
 * @member {string}
 */
Gettext.langtag = 'ja';

/**
 * クライアントの言語のlanguage部分。{@link Gettext.setLocale}から変更されます。
 * @access private
 * @member {string}
 */
Gettext.language = 'ja';

/**
 * 翻訳リソース。{@link Gettext.setLocalizedTexts}から変更されます。
 * @access private
 * @member {LocalizedTexts}
 */
Gettext.multilingualLocalizedTexts = {};

window._ = Gettext.gettext.bind(Gettext);

})();