Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
"es2021": true,
"node": true
},
"extends": "standard",
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,16 @@
"readable-stream": "^4.5.2"
},
"devDependencies": {
"@eslint/js": "^9.3.0",
"@types/chai": "latest",
"@types/content-type": "^1.1.8",
"@types/eslint__js": "^8.42.3",
"@types/mocha": "latest",
"@types/readable-stream": "^4.0.11",
"@typescript-eslint/eslint-plugin": "^7.11.0",
"@typescript-eslint/parser": "^7.11.0",
"chai": "^5.0.3",
"eslint": "^8.56.0",
"eslint": "^8.57.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-n": "^16.6.2",
Expand Down
File renamed without changes.
91 changes: 30 additions & 61 deletions src/mocompiler.js → src/mocompiler.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,19 @@
import encoding from 'encoding';
import { HEADERS, formatCharset, generateHeader, compareMsgid } from './shared.js';
import contentType from 'content-type';
import {GetTextTranslation, GetTextTranslations, Size, TranslationBuffers, Translations} from "./types.js";
import { Transform } from 'readable-stream';

/**
* @typedef {import('node:stream').Transform} Transform
* @typedef {import('./types.js').GetTextTranslation} GetTextTranslation
* @typedef {import('./types.js').GetTextTranslations} GetTextTranslations
* @typedef {import('./types.js').Translations} Translations
* @typedef {import('./types.js').WriteFunc} WriteFunc
*/

/**
* @typedef {Object} Size Data about the size of the compiled MO object.
* @property {number} msgid The size of the msgid section.
* @property {number} msgstr The size of the msgstr section.
* @property {number} total The total size of the compiled MO object.
*/

/**
* @typedef {{ msgid: Buffer, msgstr: Buffer }} TranslationBuffers A translation object partially parsed.
*/

/**
*
* @typedef {Object} CompilerOptions MO compiler options
* @property {'be'|'le'} [endian='le'] Endianness of the output buffer. Default is 'le'
*/

/**
* Exposes general compiler function. Takes a translation
* object as a parameter and returns binary MO object
*
* @param {GetTextTranslations} table Translation object
* @param {CompilerOptions} [options] MO compiler options
* @return {Buffer} Compiled binary MO object
* @param table Translation object
* @return Compiled binary MO object
*/
export default function (table, options = { endian: 'le' }) {
const compiler = new Compiler(table, options);
export default function (table: GetTextTranslations): Buffer {
const compiler = new Compiler(table);
Comment thread
erikyo marked this conversation as resolved.
Outdated

return compiler.compile();
}
Expand All @@ -46,8 +23,8 @@ export default function (table, options = { endian: 'le' }) {
* @param {Record<string, string>} headers the headers
* @return {Record<string, string>} The prepared header
*/
function prepareMoHeaders (headers) {
return Object.keys(headers).reduce((result, key) => {
function prepareMoHeaders (headers: Record<string, string>): Record<string, string> {
return Object.keys(headers).reduce((result: Record<string, string>, key: string) => {
const lowerKey = key.toLowerCase();

if (HEADERS.has(lowerKey)) {
Expand All @@ -71,10 +48,10 @@ function prepareMoHeaders (headers) {
* @param {Translations} translations
* @return {Translations}
*/
function prepareTranslations (translations) {
function prepareTranslations (translations: Translations): Translations {
return Object.keys(translations).reduce((result, msgctxt) => {
const context = translations[msgctxt];
const msgs = Object.keys(context).reduce((result, msgid) => {
const msgs = Object.keys(context).reduce((result: Record<string, GetTextTranslation>, msgid) => {
const TranslationMsgstr = context[msgid].msgstr;
const hasTranslation = TranslationMsgstr.some(item => !!item.length);

Expand All @@ -83,44 +60,36 @@ function prepareTranslations (translations) {
}

return result;
}, /** @type {Record<string, GetTextTranslation>} */({}));
},{});

if (Object.keys(msgs).length) {
result[msgctxt] = msgs;
}

return result;
}, /** @type {Translations} */({}));
}, {} as Translations);
}


/**
* Creates a MO compiler object.
* @this {Compiler & Transform}
* Creates a MO compiler object
*
* @param {GetTextTranslations} [table] Translation table as defined in the README
* @param {CompilerOptions} [options] MO compiler options
* @param table Translation table as defined in the README
*/
function Compiler (table, options = { endian: 'le' }) {
/** @type {GetTextTranslations} _table The translation table */
function Compiler (this: Compiler & Transform, table: GetTextTranslations) {
/** The translation table */
this._table = {
charset: undefined,
translations: prepareTranslations(table?.translations ?? {}),
headers: prepareMoHeaders(table?.headers ?? {})
};
} as GetTextTranslations;

this._translations = [];

/**
* @type {WriteFunc}
*/
this._writeFunc = options?.endian === 'be' ? 'writeUInt32BE' : 'writeUInt32LE';
this._writeFunc = 'writeUInt32LE';

this._handleCharset();

/**
* Magic bytes for the generated binary data
* @type {number} MAGIC file header magic value of mo file
*/
this.MAGIC = 0x950412de;
}

Expand Down Expand Up @@ -197,10 +166,10 @@ Compiler.prototype._generateList = function () {
/**
* Calculate buffer size for the final binary object
*
* @param {TranslationBuffers[]} list An array of translation strings from _generateList
* @return {Size} Size data of {msgid, msgstr, total}
* @param list An array of translation strings from _generateList
* @return Size data of {msgid, msgstr, total}
*/
Compiler.prototype._calculateSize = function (list) {
Compiler.prototype._calculateSize = function (list: TranslationBuffers[]): Size {
let msgidLength = 0;
let msgstrLength = 0;

Expand Down Expand Up @@ -231,11 +200,11 @@ Compiler.prototype._calculateSize = function (list) {
/**
* Generates the binary MO object from the translation list
*
* @param {TranslationBuffers[]} list translation list
* @param {Size} size Byte size information
* @return {Buffer} Compiled MO object
* @param list translation list
* @param size Byte size information
* @return Compiled MO object
*/
Compiler.prototype._build = function (list, size) {
Compiler.prototype._build = function (list: TranslationBuffers[], size: Size): Buffer {
const returnBuffer = Buffer.alloc(size.total);
let curPosition = 0;
let i;
Expand Down Expand Up @@ -267,8 +236,8 @@ Compiler.prototype._build = function (list, size) {
for (i = 0, len = list.length; i < len; i++) {
const msgidLength = /** @type {Buffer} */(/** @type {unknown} */(list[i].msgid));
msgidLength.copy(returnBuffer, curPosition);
returnBuffer[this._writeFunc](list[i].msgid.length, 28 + i * 8);
returnBuffer[this._writeFunc](curPosition, 28 + i * 8 + 4);
returnBuffer.writeUInt32LE(list[i].msgid.length, 28 + i * 8);
returnBuffer.writeUInt32LE(curPosition, 28 + i * 8 + 4);
returnBuffer[curPosition + list[i].msgid.length] = 0x00;
curPosition += list[i].msgid.length + 1;
}
Expand All @@ -277,8 +246,8 @@ Compiler.prototype._build = function (list, size) {
for (i = 0, len = list.length; i < len; i++) {
const msgstrLength = /** @type {Buffer} */(/** @type {unknown} */(list[i].msgstr));
msgstrLength.copy(returnBuffer, curPosition);
returnBuffer[this._writeFunc](list[i].msgstr.length, 28 + (4 + 4) * list.length + i * 8);
returnBuffer[this._writeFunc](curPosition, 28 + (4 + 4) * list.length + i * 8 + 4);
returnBuffer.writeUInt32LE(list[i].msgstr.length, 28 + (4 + 4) * list.length + i * 8);
returnBuffer.writeUInt32LE(curPosition, 28 + (4 + 4) * list.length + i * 8 + 4);
returnBuffer[curPosition + list[i].msgstr.length] = 0x00;
curPosition += list[i].msgstr.length + 1;
}
Expand Down
12 changes: 3 additions & 9 deletions src/moparser.js → src/moparser.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import encoding from 'encoding';
import { formatCharset, parseHeader } from './shared.js';

/**
* @typedef {import('./types.js').GetTextTranslations} GetTextTranslations
* @typedef {import('./types.js').GetTextTranslation} GetTextTranslation
* @typedef {import('./types.js').Translations} Translations
* @typedef {import('./types.js').WriteFunc} WriteFunc
* @typedef {import('./types.js').ReadFunc} ReadFunc
*/
import type {Parser,GetTextTranslations,GetTextTranslation,Translations,WriteFunc,ReadFunc,} from './types.js';

/**
* Parses a binary MO object into translation table
*
* @param {Buffer} buffer Binary MO object
* @param {string} [defaultCharset] Default charset to use
*/
export default function (buffer, defaultCharset) {
export default function (buffer: any, defaultCharset: string | undefined) {
const parser = new Parser(buffer, defaultCharset);

return parser.parse();
Expand All @@ -28,7 +22,7 @@ export default function (buffer, defaultCharset) {
* @param {Buffer|null} fileContents Binary MO object
* @param {string} [defaultCharset] Default charset to use
*/
function Parser (fileContents, defaultCharset = 'iso-8859-1') {
function Parser (this: Parser, fileContents: Buffer | null, defaultCharset: string = 'iso-8859-1') {
this._fileContents = fileContents;

this._charset = defaultCharset;
Expand Down
Loading