236 lines
7.8 KiB
JavaScript
236 lines
7.8 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Grammar = exports.ATTRIBUTE = void 0;
|
|
exports.correctFont = correctFont;
|
|
const DomUtil = require("../common/dom_util.js");
|
|
const engine_js_1 = require("../common/engine.js");
|
|
const LocaleUtil = require("../l10n/locale_util.js");
|
|
const locale_js_1 = require("../l10n/locale.js");
|
|
exports.ATTRIBUTE = 'grammar';
|
|
class Grammar {
|
|
static getInstance() {
|
|
Grammar.instance = Grammar.instance || new Grammar();
|
|
return Grammar.instance;
|
|
}
|
|
static parseInput(grammar) {
|
|
const attributes = {};
|
|
const components = grammar.split(':');
|
|
for (const component of components) {
|
|
const comp = component.split('=');
|
|
const key = comp[0].trim();
|
|
if (comp[1]) {
|
|
attributes[key] = comp[1].trim();
|
|
continue;
|
|
}
|
|
key.match(/^!/)
|
|
? (attributes[key.slice(1)] = false)
|
|
: (attributes[key] = true);
|
|
}
|
|
return attributes;
|
|
}
|
|
static parseState(stateStr) {
|
|
const state = {};
|
|
const corrections = stateStr.split(' ');
|
|
for (const correction of corrections) {
|
|
const corr = correction.split(':');
|
|
const key = corr[0];
|
|
const value = corr[1];
|
|
state[key] = value ? value : true;
|
|
}
|
|
return state;
|
|
}
|
|
static translateString(text) {
|
|
if (text.match(/:unit$/)) {
|
|
return Grammar.translateUnit(text);
|
|
}
|
|
const engine = engine_js_1.Engine.getInstance();
|
|
let result = engine.evaluator(text, engine.dynamicCstr);
|
|
result = result === null ? text : result;
|
|
if (Grammar.getInstance().getParameter('plural')) {
|
|
result = locale_js_1.LOCALE.FUNCTIONS.plural(result);
|
|
}
|
|
return result;
|
|
}
|
|
static translateUnit(text) {
|
|
text = Grammar.prepareUnit(text);
|
|
const engine = engine_js_1.Engine.getInstance();
|
|
const plural = Grammar.getInstance().getParameter('plural');
|
|
const strict = engine.strict;
|
|
const baseCstr = `${engine.locale}.${engine.modality}.default`;
|
|
engine.strict = true;
|
|
let cstr;
|
|
let result;
|
|
if (plural) {
|
|
cstr = engine.defaultParser.parse(baseCstr + '.plural');
|
|
result = engine.evaluator(text, cstr);
|
|
}
|
|
if (result) {
|
|
engine.strict = strict;
|
|
return result;
|
|
}
|
|
cstr = engine.defaultParser.parse(baseCstr + '.default');
|
|
result = engine.evaluator(text, cstr);
|
|
engine.strict = strict;
|
|
if (!result) {
|
|
return Grammar.cleanUnit(text);
|
|
}
|
|
if (plural) {
|
|
result = locale_js_1.LOCALE.FUNCTIONS.plural(result);
|
|
}
|
|
return result;
|
|
}
|
|
static prepareUnit(text) {
|
|
const match = text.match(/:unit$/);
|
|
return match
|
|
? text.slice(0, match.index).replace(/\s+/g, ' ') +
|
|
text.slice(match.index)
|
|
: text;
|
|
}
|
|
static cleanUnit(text) {
|
|
if (text.match(/:unit$/)) {
|
|
return text.replace(/:unit$/, '');
|
|
}
|
|
return text;
|
|
}
|
|
clear() {
|
|
this.parameters_ = {};
|
|
this.stateStack_ = [];
|
|
}
|
|
setParameter(parameter, value) {
|
|
const oldValue = this.parameters_[parameter];
|
|
value
|
|
? (this.parameters_[parameter] = value)
|
|
: delete this.parameters_[parameter];
|
|
return oldValue;
|
|
}
|
|
getParameter(parameter) {
|
|
return this.parameters_[parameter];
|
|
}
|
|
setCorrection(correction, func) {
|
|
this.corrections_[correction] = func;
|
|
}
|
|
setPreprocessor(preprocessor, func) {
|
|
this.preprocessors_[preprocessor] = func;
|
|
}
|
|
getCorrection(correction) {
|
|
return this.corrections_[correction];
|
|
}
|
|
getState() {
|
|
const pairs = [];
|
|
for (const [key, val] of Object.entries(this.parameters_)) {
|
|
pairs.push(typeof val === 'string' ? key + ':' + val : key);
|
|
}
|
|
return pairs.join(' ');
|
|
}
|
|
processSingles() {
|
|
const assignment = {};
|
|
for (const single of this.singles) {
|
|
assignment[single] = false;
|
|
}
|
|
this.singles = [];
|
|
this.pushState(assignment);
|
|
}
|
|
pushState(assignment) {
|
|
for (let [key, value] of Object.entries(assignment)) {
|
|
if (key.match(/^\?/)) {
|
|
delete assignment[key];
|
|
key = key.slice(1);
|
|
this.singles.push(key);
|
|
}
|
|
assignment[key] = this.setParameter(key, value);
|
|
}
|
|
this.stateStack_.push(assignment);
|
|
}
|
|
popState() {
|
|
const assignment = this.stateStack_.pop();
|
|
for (const [key, val] of Object.entries(assignment)) {
|
|
this.setParameter(key, val);
|
|
}
|
|
}
|
|
setAttribute(node) {
|
|
if (node && node.nodeType === DomUtil.NodeType.ELEMENT_NODE) {
|
|
const state = this.getState();
|
|
if (state) {
|
|
node.setAttribute(exports.ATTRIBUTE, state);
|
|
}
|
|
}
|
|
}
|
|
preprocess(text) {
|
|
return this.runProcessors(text, this.preprocessors_);
|
|
}
|
|
correct(text) {
|
|
return this.runProcessors(text, this.corrections_);
|
|
}
|
|
apply(text, opt_flags) {
|
|
this.currentFlags = opt_flags || {};
|
|
text =
|
|
this.currentFlags.adjust || this.currentFlags.preprocess
|
|
? Grammar.getInstance().preprocess(text)
|
|
: text;
|
|
if (this.parameters_['translate'] || this.currentFlags.translate) {
|
|
text = Grammar.translateString(text);
|
|
}
|
|
text =
|
|
this.currentFlags.adjust || this.currentFlags.correct
|
|
? Grammar.getInstance().correct(text)
|
|
: text;
|
|
this.currentFlags = {};
|
|
return text;
|
|
}
|
|
runProcessors(text, funcs) {
|
|
for (const [key, val] of Object.entries(this.parameters_)) {
|
|
const func = funcs[key];
|
|
if (!func) {
|
|
continue;
|
|
}
|
|
text = val === true ? func(text) : func(text, val);
|
|
}
|
|
return text;
|
|
}
|
|
constructor() {
|
|
this.currentFlags = {};
|
|
this.parameters_ = {};
|
|
this.corrections_ = {};
|
|
this.preprocessors_ = {};
|
|
this.stateStack_ = [];
|
|
this.singles = [];
|
|
}
|
|
}
|
|
exports.Grammar = Grammar;
|
|
function correctFont(text, correction) {
|
|
if (!correction || !text) {
|
|
return text;
|
|
}
|
|
const regexp = locale_js_1.LOCALE.FUNCTIONS.fontRegexp(LocaleUtil.localFont(correction));
|
|
return text.replace(regexp, '');
|
|
}
|
|
function correctCaps(text) {
|
|
let cap = locale_js_1.LOCALE.ALPHABETS.capPrefix[engine_js_1.Engine.getInstance().domain];
|
|
if (typeof cap === 'undefined') {
|
|
cap = locale_js_1.LOCALE.ALPHABETS.capPrefix['default'];
|
|
}
|
|
return correctFont(text, cap);
|
|
}
|
|
function addAnnotation(text, annotation) {
|
|
return text + ':' + annotation;
|
|
}
|
|
function numbersToAlpha(text) {
|
|
return text.match(/\d+/)
|
|
? locale_js_1.LOCALE.NUMBERS.numberToWords(parseInt(text, 10))
|
|
: text;
|
|
}
|
|
function noTranslateText(text) {
|
|
if (text.match(new RegExp('^[' + locale_js_1.LOCALE.MESSAGES.regexp.TEXT + ']+$'))) {
|
|
Grammar.getInstance().currentFlags['translate'] = false;
|
|
}
|
|
return text;
|
|
}
|
|
Grammar.getInstance().setCorrection('localFont', LocaleUtil.localFont);
|
|
Grammar.getInstance().setCorrection('localRole', LocaleUtil.localRole);
|
|
Grammar.getInstance().setCorrection('localEnclose', LocaleUtil.localEnclose);
|
|
Grammar.getInstance().setCorrection('ignoreFont', correctFont);
|
|
Grammar.getInstance().setPreprocessor('annotation', addAnnotation);
|
|
Grammar.getInstance().setPreprocessor('noTranslateText', noTranslateText);
|
|
Grammar.getInstance().setCorrection('ignoreCaps', correctCaps);
|
|
Grammar.getInstance().setPreprocessor('numbers2alpha', numbersToAlpha);
|