import Template from "./Template";
-const _languageItems = new Map<string, string | Template>();
+import { add as addToStore, Phrase } from "./Language/Store";
+
+export { get } from "./Language/Store";
/**
* Adds all the language items in the given object to the store.
* Adds a single language item to the store.
*/
export function add(key: string, value: string): void {
- _languageItems.set(key, value);
+ addToStore(key, compile(value));
}
/**
- * Fetches the language item specified by the given key.
- * If the language item is a string it will be evaluated as
- * WoltLabSuite/Core/Template with the given parameters.
- *
- * @param {string} key Language item to return.
- * @param {Object=} parameters Parameters to provide to WoltLabSuite/Core/Template.
- * @return {string}
+ * Compiles the given value into a phrase.
*/
-export function get(key: string, parameters?: object): string {
- let value = _languageItems.get(key);
- if (value === undefined) {
- return key;
+function compile(value: string): Phrase {
+ try {
+ const template = new Template(value);
+ return template.fetch.bind(template);
+ } catch (e) {
+ return function () {
+ return value;
+ };
}
-
- if (Template === undefined) {
- // @ts-expect-error: This is required due to a circular dependency.
- Template = require("./Template");
- }
-
- if (typeof value === "string") {
- // lazily convert to WCF.Template
- try {
- _languageItems.set(key, new Template(value));
- } catch (e) {
- _languageItems.set(
- key,
- new Template(
- "{literal}" + value.replace(/{\/literal}/g, "{/literal}{ldelim}/literal}{literal}") + "{/literal}",
- ),
- );
- }
- value = _languageItems.get(key);
- }
-
- if (value instanceof Template) {
- value = value.fetch(parameters || {});
- }
-
- return value as string;
}
interface LanguageItems {
--- /dev/null
+/**
+ * Handles the low level management of language items.
+ *
+ * @author Tim Duesterhus
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLabSuite/Core/Language/Store
+ */
+
+const languageItems = new Map<string, Phrase>();
+
+/**
+ * Fetches the language item specified by the given key.
+ *
+ * The given parameters are passed to the compiled Phrase.
+ */
+export function get(key: string, parameters: object = {}): string {
+ const value = languageItems.get(key);
+ if (value === undefined) {
+ return key;
+ }
+
+ return value(parameters);
+}
+
+/**
+ * Adds a single language item to the store.
+ */
+export function add(key: string, value: Phrase): void {
+ languageItems.set(key, value);
+}
+
+/**
+ * Represents a compiled phrase.
+ */
+export type Phrase = (parameters: object) => string;
/**
- * WoltLabSuite/Core/Template provides a template scripting compiler similar
- * to the PHP one of WoltLab Suite Core. It supports a limited
- * set of useful commands and compiles templates down to a pure
- * JavaScript Function.
+ * Provides a high level wrapper around the Template/Compiler.
*
* @author Tim Duesterhus
* @copyright 2001-2019 WoltLab GmbH
*/
import * as Core from "./Core";
-import * as parser from "./Template.grammar";
-import * as StringUtil from "./StringUtil";
-import * as Language from "./Language";
import * as I18nPlural from "./I18n/Plural";
+import * as LanguageStore from "./Language/Store";
+import * as StringUtil from "./StringUtil";
+import { compile, CompiledTemplate } from "./Template/Compiler";
// @todo: still required?
// work around bug in AMD module generation of Jison
parser = new Parser();*/
class Template {
- constructor(template: string) {
- if (Language === undefined) {
- // @ts-expect-error: This is required due to a circular dependency.
- Language = require("./Language");
- }
- if (StringUtil === undefined) {
- // @ts-expect-error: This is required due to a circular dependency.
- StringUtil = require("./StringUtil");
- }
+ private compiled: CompiledTemplate;
+ constructor(template: string) {
try {
- template = parser.parse(template) as string;
- template =
- "var tmp = {};\n" +
- "for (var key in v) tmp[key] = v[key];\n" +
- "v = tmp;\n" +
- "v.__wcf = window.WCF; v.__window = window;\n" +
- "return " +
- template;
-
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
- this.fetch = new Function("StringUtil", "Language", "I18nPlural", "v", template).bind(
- undefined,
- StringUtil,
- Language,
- I18nPlural,
- );
+ this.compiled = compile(template);
} catch (e) {
console.debug(e.message);
throw e;
/**
* Evaluates the Template using the given parameters.
*/
- fetch(_v: object): string {
- // this will be replaced in the init function
- throw new Error("This Template is not initialized.");
+ fetch(v: object): string {
+ return this.compiled(StringUtil, LanguageStore, I18nPlural, v);
}
}
--- /dev/null
+/**
+ * WoltLabSuite/Core/Template/Compiler provides a template scripting compiler
+ * similar to the PHP one of WoltLab Suite Core. It supports a limited set of
+ * useful commands and compiles templates down to a pure JavaScript Function.
+ *
+ * @author Tim Duesterhus
+ * @copyright 2001-2021 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLabSuite/Core/Template/Compiler
+ */
+
+import * as parser from "../Template.grammar";
+import type { escapeHTML, formatNumeric } from "../StringUtil";
+import type { get as getLanguage } from "../Language";
+import type { getCategoryFromTemplateParameters } from "../I18n/Plural";
+
+interface TemplateLanguage {
+ get: typeof getLanguage;
+}
+
+interface TemplateStringUtil {
+ escapeHTML: typeof escapeHTML;
+ formatNumeric: typeof formatNumeric;
+}
+
+interface TemplatePlural {
+ getCategoryFromTemplateParameters: typeof getCategoryFromTemplateParameters;
+}
+
+export type CompiledTemplate = (S: TemplateStringUtil, L: TemplateLanguage, P: TemplatePlural, v: object) => string;
+
+/**
+ * Compiles the given template.
+ */
+export function compile(template: string): CompiledTemplate {
+ template = parser.parse(template) as string;
+ template =
+ "var tmp = {};\n" +
+ "for (var key in v) tmp[key] = v[key];\n" +
+ "v = tmp;\n" +
+ "v.__wcf = window.WCF; v.__window = window;\n" +
+ "return " +
+ template;
+
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
+ return new Function("StringUtil", "Language", "I18nPlural", "v", template) as CompiledTemplate;
+}
* @module Language (alias)
* @module WoltLabSuite/Core/Language
*/
-define(["require", "exports", "tslib", "./Template"], function (require, exports, tslib_1, Template_1) {
+define(["require", "exports", "tslib", "./Template", "./Language/Store", "./Language/Store"], function (require, exports, tslib_1, Template_1, Store_1, Store_2) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
- exports.get = exports.add = exports.addObject = void 0;
+ exports.add = exports.addObject = exports.get = void 0;
Template_1 = tslib_1.__importDefault(Template_1);
- const _languageItems = new Map();
+ Object.defineProperty(exports, "get", { enumerable: true, get: function () { return Store_2.get; } });
/**
* Adds all the language items in the given object to the store.
*/
* Adds a single language item to the store.
*/
function add(key, value) {
- _languageItems.set(key, value);
+ Store_1.add(key, compile(value));
}
exports.add = add;
/**
- * Fetches the language item specified by the given key.
- * If the language item is a string it will be evaluated as
- * WoltLabSuite/Core/Template with the given parameters.
- *
- * @param {string} key Language item to return.
- * @param {Object=} parameters Parameters to provide to WoltLabSuite/Core/Template.
- * @return {string}
+ * Compiles the given value into a phrase.
*/
- function get(key, parameters) {
- let value = _languageItems.get(key);
- if (value === undefined) {
- return key;
+ function compile(value) {
+ try {
+ const template = new Template_1.default(value);
+ return template.fetch.bind(template);
}
- if (Template_1.default === undefined) {
- // @ts-expect-error: This is required due to a circular dependency.
- Template_1.default = require("./Template");
+ catch (e) {
+ return function () {
+ return value;
+ };
}
- if (typeof value === "string") {
- // lazily convert to WCF.Template
- try {
- _languageItems.set(key, new Template_1.default(value));
- }
- catch (e) {
- _languageItems.set(key, new Template_1.default("{literal}" + value.replace(/{\/literal}/g, "{/literal}{ldelim}/literal}{literal}") + "{/literal}"));
- }
- value = _languageItems.get(key);
- }
- if (value instanceof Template_1.default) {
- value = value.fetch(parameters || {});
- }
- return value;
}
- exports.get = get;
});
--- /dev/null
+/**
+ * Handles the low level management of language items.
+ *
+ * @author Tim Duesterhus
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLabSuite/Core/Language/Store
+ */
+define(["require", "exports"], function (require, exports) {
+ "use strict";
+ Object.defineProperty(exports, "__esModule", { value: true });
+ exports.add = exports.get = void 0;
+ const languageItems = new Map();
+ /**
+ * Fetches the language item specified by the given key.
+ *
+ * The given parameters are passed to the compiled Phrase.
+ */
+ function get(key, parameters = {}) {
+ const value = languageItems.get(key);
+ if (value === undefined) {
+ return key;
+ }
+ return value(parameters);
+ }
+ exports.get = get;
+ /**
+ * Adds a single language item to the store.
+ */
+ function add(key, value) {
+ languageItems.set(key, value);
+ }
+ exports.add = add;
+});
/**
- * WoltLabSuite/Core/Template provides a template scripting compiler similar
- * to the PHP one of WoltLab Suite Core. It supports a limited
- * set of useful commands and compiles templates down to a pure
- * JavaScript Function.
+ * Provides a high level wrapper around the Template/Compiler.
*
* @author Tim Duesterhus
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @module WoltLabSuite/Core/Template
*/
-define(["require", "exports", "tslib", "./Core", "./Template.grammar", "./StringUtil", "./Language", "./I18n/Plural"], function (require, exports, tslib_1, Core, parser, StringUtil, Language, I18nPlural) {
+define(["require", "exports", "tslib", "./Core", "./I18n/Plural", "./Language/Store", "./StringUtil", "./Template/Compiler"], function (require, exports, tslib_1, Core, I18nPlural, LanguageStore, StringUtil, Compiler_1) {
"use strict";
Core = tslib_1.__importStar(Core);
- parser = tslib_1.__importStar(parser);
- StringUtil = tslib_1.__importStar(StringUtil);
- Language = tslib_1.__importStar(Language);
I18nPlural = tslib_1.__importStar(I18nPlural);
+ LanguageStore = tslib_1.__importStar(LanguageStore);
+ StringUtil = tslib_1.__importStar(StringUtil);
// @todo: still required?
// work around bug in AMD module generation of Jison
/*function Parser() {
parser = new Parser();*/
class Template {
constructor(template) {
- if (Language === undefined) {
- // @ts-expect-error: This is required due to a circular dependency.
- Language = require("./Language");
- }
- if (StringUtil === undefined) {
- // @ts-expect-error: This is required due to a circular dependency.
- StringUtil = require("./StringUtil");
- }
try {
- template = parser.parse(template);
- template =
- "var tmp = {};\n" +
- "for (var key in v) tmp[key] = v[key];\n" +
- "v = tmp;\n" +
- "v.__wcf = window.WCF; v.__window = window;\n" +
- "return " +
- template;
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
- this.fetch = new Function("StringUtil", "Language", "I18nPlural", "v", template).bind(undefined, StringUtil, Language, I18nPlural);
+ this.compiled = Compiler_1.compile(template);
}
catch (e) {
console.debug(e.message);
/**
* Evaluates the Template using the given parameters.
*/
- fetch(_v) {
- // this will be replaced in the init function
- throw new Error("This Template is not initialized.");
+ fetch(v) {
+ return this.compiled(StringUtil, LanguageStore, I18nPlural, v);
}
}
Object.defineProperty(Template, "callbacks", {
--- /dev/null
+/**
+ * WoltLabSuite/Core/Template/Compiler provides a template scripting compiler
+ * similar to the PHP one of WoltLab Suite Core. It supports a limited set of
+ * useful commands and compiles templates down to a pure JavaScript Function.
+ *
+ * @author Tim Duesterhus
+ * @copyright 2001-2021 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLabSuite/Core/Template/Compiler
+ */
+define(["require", "exports", "tslib", "../Template.grammar"], function (require, exports, tslib_1, parser) {
+ "use strict";
+ Object.defineProperty(exports, "__esModule", { value: true });
+ exports.compile = void 0;
+ parser = tslib_1.__importStar(parser);
+ /**
+ * Compiles the given template.
+ */
+ function compile(template) {
+ template = parser.parse(template);
+ template =
+ "var tmp = {};\n" +
+ "for (var key in v) tmp[key] = v[key];\n" +
+ "v = tmp;\n" +
+ "v.__wcf = window.WCF; v.__window = window;\n" +
+ "return " +
+ template;
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
+ return new Function("StringUtil", "Language", "I18nPlural", "v", template);
+ }
+ exports.compile = compile;
+});