-
Notifications
You must be signed in to change notification settings - Fork 45
v8.1.0 Update #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
v8.1.0 Update #86
Changes from all commits
f3d5cf8
9e477d8
052d3d2
d18bbdb
2f94ed7
955eaa2
c40a44c
f360d08
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
/node_modules | ||
/lib | ||
/@types | ||
npm-debug.log | ||
.DS_Store |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/test | ||
/src | ||
.eslintrc.js | ||
.gitignore |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { poParse, poStream } from './poparser.js'; | ||
import poCompiler from './pocompiler.js'; | ||
import moParser from './moparser.js'; | ||
import moCompiler from './mocompiler.js'; | ||
|
||
/** | ||
* Translation parser and compiler for PO files | ||
* @see https://www.gnu.org/software/gettext/manual/html_node/PO.html | ||
*/ | ||
export const po = { | ||
parse: poParse, | ||
createParseStream: poStream, | ||
compile: poCompiler | ||
}; | ||
|
||
/** | ||
* Translation parser and compiler for MO files | ||
* @see https://www.gnu.org/software/gettext/manual/html_node/MO.html | ||
*/ | ||
export const mo = { | ||
parse: moParser, | ||
compile: moCompiler | ||
}; | ||
|
||
export default { mo, po }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,119 @@ | ||
import { Buffer } from 'safe-buffer'; | ||
import encoding from 'encoding'; | ||
import { HEADERS, formatCharset, generateHeader, compareMsgid } from './shared.js'; | ||
import contentType from 'content-type'; | ||
|
||
/** | ||
* @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. | ||
*/ | ||
|
||
/** | ||
* Exposes general compiler function. Takes a translation | ||
* object as a parameter and returns binary MO object | ||
* | ||
* @param {Object} table Translation object | ||
* @param {GetTextTranslations} table Translation object | ||
* @return {Buffer} Compiled binary MO object | ||
*/ | ||
export default function (table) { | ||
const compiler = new Compiler(table); | ||
|
||
return compiler.compile(); | ||
}; | ||
} | ||
|
||
/** | ||
* Creates a MO compiler object. | ||
* | ||
* @constructor | ||
* @param {Object} table Translation table as defined in the README | ||
* Prepare the header object to be compatible with MO compiler | ||
* @param {Record<string, string>} headers the headers | ||
* @return {Record<string, string>} The prepared header | ||
*/ | ||
function Compiler (table = {}) { | ||
this._table = table; | ||
|
||
let { headers = {}, translations = {} } = this._table; | ||
|
||
headers = Object.keys(headers).reduce((result, key) => { | ||
function prepareMoHeaders (headers) { | ||
return Object.keys(headers).reduce((result, key) => { | ||
const lowerKey = key.toLowerCase(); | ||
|
||
if (HEADERS.has(lowerKey)) { | ||
// POT-Creation-Date is removed in MO (see https://savannah.gnu.org/bugs/?49654) | ||
if (lowerKey !== 'pot-creation-date') { | ||
result[HEADERS.get(lowerKey)] = headers[key]; | ||
const value = HEADERS.get(lowerKey); | ||
if (value) { | ||
result[value] = headers[key]; | ||
} | ||
} | ||
} else { | ||
result[key] = headers[key]; | ||
} | ||
|
||
return result; | ||
}, {}); | ||
}, /** @type {Record<string, string>} */ ({})); | ||
} | ||
|
||
// filter out empty translations | ||
translations = Object.keys(translations).reduce((result, msgctxt) => { | ||
/** | ||
* Prepare the translation object to be compatible with MO compiler | ||
* @param {Translations} translations | ||
* @return {Translations} | ||
*/ | ||
function prepareTranslations (translations) { | ||
return Object.keys(translations).reduce((result, msgctxt) => { | ||
const context = translations[msgctxt]; | ||
const msgs = Object.keys(context).reduce((result, msgid) => { | ||
const hasTranslation = context[msgid].msgstr.some(item => !!item.length); | ||
const TranslationMsgstr = context[msgid].msgstr; | ||
const hasTranslation = TranslationMsgstr.some(item => !!item.length); | ||
|
||
if (hasTranslation) { | ||
result[msgid] = context[msgid]; | ||
} | ||
|
||
return result; | ||
}, {}); | ||
}, /** @type {Record<string, GetTextTranslation>} */({})); | ||
|
||
if (Object.keys(msgs).length) { | ||
result[msgctxt] = msgs; | ||
} | ||
|
||
return result; | ||
}, {}); | ||
}, /** @type {Translations} */({})); | ||
} | ||
|
||
this._table.translations = translations; | ||
this._table.headers = headers; | ||
/** | ||
* Creates a MO compiler object. | ||
* @this {Compiler & Transform} | ||
* | ||
* @param {GetTextTranslations} [table] Translation table as defined in the README | ||
*/ | ||
function Compiler (table) { | ||
/** @type {GetTextTranslations} _table The translation table */ | ||
this._table = { | ||
charset: undefined, | ||
translations: prepareTranslations(table?.translations ?? {}), | ||
headers: prepareMoHeaders(table?.headers ?? {}) | ||
}; | ||
|
||
this._translations = []; | ||
|
||
/** | ||
* @type {WriteFunc} | ||
*/ | ||
this._writeFunc = 'writeUInt32LE'; | ||
|
||
this._handleCharset(); | ||
} | ||
|
||
/** | ||
* Magic bytes for the generated binary data | ||
*/ | ||
Compiler.prototype.MAGIC = 0x950412de; | ||
/** | ||
* Magic bytes for the generated binary data | ||
* @type {number} MAGIC file header magic value of mo file | ||
*/ | ||
this.MAGIC = 0x950412de; | ||
} | ||
|
||
/** | ||
* Handles header values, replaces or adds (if needed) a charset property | ||
|
@@ -96,17 +134,19 @@ Compiler.prototype._handleCharset = function () { | |
|
||
/** | ||
* Generates an array of translation strings | ||
* in the form of [{msgid:... , msgstr:...}] | ||
* in the form of [{msgid:..., msgstr: ...}] | ||
* | ||
* @return {Array} Translation strings array | ||
*/ | ||
Compiler.prototype._generateList = function () { | ||
/** @type {TranslationBuffers[]} */ | ||
const list = []; | ||
|
||
list.push({ | ||
msgid: Buffer.alloc(0), | ||
msgstr: encoding.convert(generateHeader(this._table.headers), this._table.charset) | ||
}); | ||
if ('headers' in this._table) { | ||
list.push({ | ||
msgid: Buffer.alloc(0), | ||
msgstr: encoding.convert(generateHeader(this._table.headers), this._table.charset) | ||
}); | ||
} | ||
|
||
Object.keys(this._table.translations).forEach(msgctxt => { | ||
if (typeof this._table.translations[msgctxt] !== 'object') { | ||
|
@@ -133,7 +173,7 @@ Compiler.prototype._generateList = function () { | |
key += '\u0000' + msgidPlural; | ||
} | ||
|
||
const value = [].concat(this._table.translations[msgctxt][msgid].msgstr || []).join('\u0000'); | ||
const value = /** @type {string[]} */([]).concat(this._table.translations[msgctxt][msgid].msgstr ?? []).join('\u0000'); | ||
|
||
list.push({ | ||
msgid: encoding.convert(key, this._table.charset), | ||
|
@@ -148,20 +188,19 @@ Compiler.prototype._generateList = function () { | |
/** | ||
* Calculate buffer size for the final binary object | ||
* | ||
* @param {Array} list An array of translation strings from _generateList | ||
* @return {Object} Size data of {msgid, msgstr, total} | ||
* @param {TranslationBuffers[]} list An array of translation strings from _generateList | ||
* @return {Size} Size data of {msgid, msgstr, total} | ||
*/ | ||
Compiler.prototype._calculateSize = function (list) { | ||
let msgidLength = 0; | ||
let msgstrLength = 0; | ||
let totalLength = 0; | ||
|
||
list.forEach(translation => { | ||
msgidLength += translation.msgid.length + 1; // + extra 0x00 | ||
msgstrLength += translation.msgstr.length + 1; // + extra 0x00 | ||
}); | ||
|
||
totalLength = 4 + // magic number | ||
const totalLength = 4 + // magic number | ||
4 + // revision | ||
4 + // string count | ||
4 + // original string table offset | ||
|
@@ -183,9 +222,9 @@ Compiler.prototype._calculateSize = function (list) { | |
/** | ||
* Generates the binary MO object from the translation list | ||
* | ||
* @param {Array} list translation list | ||
* @param {Object} size Byte size information | ||
* @return {Buffer} Compiled MO object | ||
* @param {TranslationBuffers[]} list translation list | ||
* @param {Size} size Byte size information | ||
* @return {Buffer} Compiled MO object | ||
Comment on lines
+226
to
+227
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should remove these spaces... also would be nice to add a JSDoc eslint rules. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep you are right, it seems that jsdocs aren't formatted at all. What do you suggest to fix that issue? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @erikyo I have a branch that is almost done, in which I manually format them. I looked into using |
||
*/ | ||
Compiler.prototype._build = function (list, size) { | ||
const returnBuffer = Buffer.alloc(size.total); | ||
|
@@ -214,21 +253,23 @@ Compiler.prototype._build = function (list, size) { | |
// hash table offset | ||
returnBuffer[this._writeFunc](28 + (4 + 4) * list.length * 2, 24); | ||
|
||
// build originals table | ||
// Build original table | ||
curPosition = 28 + 2 * (4 + 4) * list.length; | ||
for (i = 0, len = list.length; i < len; i++) { | ||
list[i].msgid.copy(returnBuffer, curPosition); | ||
returnBuffer[this._writeFunc](list[i].msgid.length, 28 + i * 8); | ||
returnBuffer[this._writeFunc](curPosition, 28 + i * 8 + 4); | ||
const msgidLength = /** @type {Buffer} */(/** @type {unknown} */(list[i].msgid)); | ||
msgidLength.copy(returnBuffer, curPosition); | ||
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; | ||
} | ||
|
||
// build translations table | ||
// build translation table | ||
for (i = 0, len = list.length; i < len; i++) { | ||
list[i].msgstr.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); | ||
const msgstrLength = /** @type {Buffer} */(/** @type {unknown} */(list[i].msgstr)); | ||
msgstrLength.copy(returnBuffer, curPosition); | ||
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; | ||
} | ||
|
@@ -237,8 +278,9 @@ Compiler.prototype._build = function (list, size) { | |
}; | ||
|
||
/** | ||
* Compiles translation object into a binary MO object | ||
* Compiles a translation object into a binary MO object | ||
* | ||
* @interface | ||
* @return {Buffer} Compiled MO object | ||
*/ | ||
Compiler.prototype.compile = function () { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,324 @@ | ||
import { HEADERS, foldLine, compareMsgid, formatCharset, generateHeader } from './shared.js'; | ||
import contentType from 'content-type'; | ||
|
||
import encoding from 'encoding'; | ||
|
||
/** | ||
* @typedef {import('./types.js').GetTextTranslations} GetTextTranslations | ||
* @typedef {import('./types.js').GetTextTranslation} GetTextTranslation | ||
* @typedef {import('./types.js').GetTextComment} GetTextComment | ||
* @typedef {import('./types.js').Translations} Translations | ||
* @typedef {import('./types.js').ParserOptions} ParserOptions | ||
*/ | ||
|
||
/** | ||
* @typedef {Partial<Omit<GetTextTranslation, 'msgstr'>> & { msgstr?: string | string[] }} PreOutputTranslation | ||
*/ | ||
|
||
/** | ||
* Exposes general compiler function. Takes a translation | ||
* object as a parameter and returns PO object | ||
* | ||
* @param {GetTextTranslations} table Translation object | ||
* @param {ParserOptions} [options] Options | ||
* @return {Buffer} The compiled PO object | ||
*/ | ||
export default function (table, options) { | ||
const compiler = new Compiler(table, options); | ||
|
||
return compiler.compile(); | ||
} | ||
|
||
/** | ||
* Takes the header object and converts all headers into the lowercase format | ||
* | ||
* @param {Record<string, string>} headersRaw the headers to prepare | ||
* @returns {Record<string, string>} the headers in the lowercase format | ||
*/ | ||
export function preparePoHeaders (headersRaw) { | ||
return Object.keys(headersRaw).reduce((result, key) => { | ||
const lowerKey = key.toLowerCase(); | ||
const value = HEADERS.get(lowerKey); | ||
|
||
if (typeof value === 'string') { | ||
result[value] = headersRaw[key]; | ||
} else { | ||
result[key] = headersRaw[key]; | ||
} | ||
|
||
return result; | ||
}, /** @type {Record<string, string>} */ ({})); | ||
} | ||
|
||
/** | ||
* Creates a PO compiler object. | ||
* | ||
* @constructor | ||
* @param {GetTextTranslations} [table] Translation table to be compiled | ||
* @param {ParserOptions} [options] Options | ||
*/ | ||
function Compiler (table, options) { | ||
this._table = table ?? { | ||
headers: {}, | ||
charset: undefined, | ||
translations: {} | ||
}; | ||
this._table.translations = { ...this._table.translations }; | ||
|
||
/** @type {ParserOptions} _options The Options object */ | ||
this._options = { | ||
foldLength: 76, | ||
escapeCharacters: true, | ||
sort: false, | ||
eol: '\n', | ||
...options | ||
}; | ||
|
||
/** @type {Record<string, string>}} the translation table */ | ||
this._table.headers = preparePoHeaders(this._table.headers ?? {}); | ||
|
||
this._translations = []; | ||
|
||
this._handleCharset(); | ||
} | ||
|
||
/** | ||
* Converts a comment object to a comment string. The comment object is | ||
* in the form of {translator: '', reference: '', extracted: '', flag: '', previous: ''} | ||
* | ||
* @param {Record<string, string>} comments A comments object | ||
* @return {string} A comment string for the PO file | ||
*/ | ||
Compiler.prototype._drawComments = function (comments) { | ||
/** @var {Record<string, string[]>[]} lines The comment lines to be returned */ | ||
const lines = []; | ||
/** @var {{key: GetTextComment, prefix: string}} type The comment type */ | ||
const types = [{ | ||
key: 'translator', | ||
prefix: '# ' | ||
}, { | ||
key: 'reference', | ||
prefix: '#: ' | ||
}, { | ||
key: 'extracted', | ||
prefix: '#. ' | ||
}, { | ||
key: 'flag', | ||
prefix: '#, ' | ||
}, { | ||
key: 'previous', | ||
prefix: '#| ' | ||
}]; | ||
|
||
for (const type of types) { | ||
/** @var {string} value The comment type */ | ||
const value = type.key; | ||
|
||
// ignore empty comments | ||
if (!(value in comments)) { continue; } | ||
|
||
const commentLines = comments[value].split(/\r?\n|\r/); | ||
|
||
// add comment lines to comments Array | ||
for (const line of commentLines) { | ||
lines.push(`${type.prefix}${line}`); | ||
} | ||
} | ||
|
||
return lines.length ? lines.join(this._options.eol) : ''; | ||
}; | ||
|
||
/** | ||
* Builds a PO string for a single translation object | ||
* | ||
* @param {PreOutputTranslation} block Translation object | ||
* @param {Partial<PreOutputTranslation>} [override] Properties of this object will override `block` properties | ||
* @param {boolean} [obsolete] Block is obsolete and must be commented out | ||
* @return {string} Translation string for a single object | ||
*/ | ||
Compiler.prototype._drawBlock = function (block, override = {}, obsolete = false) { | ||
const response = []; | ||
const msgctxt = override.msgctxt || block.msgctxt; | ||
const msgid = override.msgid || block.msgid; | ||
const msgidPlural = override.msgid_plural || block.msgid_plural; | ||
const msgstrData = override.msgstr || block.msgstr; | ||
const msgstr = Array.isArray(msgstrData) ? [...msgstrData] : [msgstrData]; | ||
|
||
/** @type {GetTextComment|undefined} */ | ||
const comments = override.comments || block.comments; | ||
if (comments) { | ||
const drawnComments = this._drawComments(comments); | ||
if (drawnComments) { | ||
response.push(drawnComments); | ||
} | ||
} | ||
|
||
if (msgctxt) { | ||
response.push(this._addPOString('msgctxt', msgctxt, obsolete)); | ||
} | ||
|
||
response.push(this._addPOString('msgid', msgid || '', obsolete)); | ||
|
||
if (msgidPlural) { | ||
response.push(this._addPOString('msgid_plural', msgidPlural, obsolete)); | ||
|
||
msgstr.forEach((msgstr, i) => { | ||
response.push(this._addPOString(`msgstr[${i}]`, msgstr || '', obsolete)); | ||
}); | ||
} else { | ||
response.push(this._addPOString('msgstr', msgstr[0] || '', obsolete)); | ||
} | ||
|
||
return response.join(this._options.eol); | ||
}; | ||
|
||
/** | ||
* Escapes and joins a key and a value for the PO string | ||
* | ||
* @param {string} key Key name | ||
* @param {string} value Key value | ||
* @param {boolean} [obsolete] PO string is obsolete and must be commented out | ||
* @return {string} Joined and escaped key-value pair | ||
*/ | ||
Compiler.prototype._addPOString = function (key = '', value = '', obsolete = false) { | ||
key = key.toString(); | ||
if (obsolete) { | ||
key = '#~ ' + key; | ||
} | ||
|
||
let { foldLength, eol, escapeCharacters } = this._options; | ||
|
||
// escape newlines and quotes | ||
if (escapeCharacters) { | ||
value = value.toString() | ||
.replace(/\\/g, '\\\\') | ||
.replace(/"/g, '\\"') | ||
.replace(/\t/g, '\\t') | ||
.replace(/\r/g, '\\r'); | ||
} | ||
|
||
value = value.replace(/\n/g, '\\n'); // need to escape new line characters regardless | ||
|
||
let lines = [value]; | ||
|
||
if (obsolete) { | ||
eol = eol + '#~ '; | ||
} | ||
|
||
if (foldLength && foldLength > 0) { | ||
lines = foldLine(value, foldLength); | ||
} else { | ||
// split only on new lines | ||
if (escapeCharacters) { | ||
lines = value.split(/\\n/g); | ||
for (let i = 0; i < lines.length - 1; i++) { | ||
lines[i] = `${lines[i]}\\n`; | ||
} | ||
if (lines.length && lines[lines.length - 1] === '') { | ||
lines.splice(-1, 1); | ||
} | ||
} | ||
} | ||
|
||
if (lines.length < 2) { | ||
return `${key} "${lines.shift() || ''}"`; | ||
} | ||
|
||
return `${key} ""${eol}"${lines.join(`"${eol}"`)}"`; | ||
}; | ||
|
||
/** | ||
* Handles header values, replaces or adds (if needed) a charset property | ||
*/ | ||
Compiler.prototype._handleCharset = function () { | ||
if (this._table.headers) { | ||
const ct = contentType.parse(this._table.headers['Content-Type'] || 'text/plain'); | ||
|
||
const charset = formatCharset(this._table.charset || ct.parameters.charset || 'utf-8'); | ||
|
||
// clean up content-type charset independently using fallback if missing | ||
if (ct.parameters.charset) { | ||
ct.parameters.charset = formatCharset(ct.parameters.charset); | ||
} | ||
|
||
this._table.charset = charset; | ||
this._table.headers['Content-Type'] = contentType.format(ct); | ||
} | ||
}; | ||
|
||
/** | ||
* Flatten and sort translations object | ||
* | ||
* @param {Translations} section Object to be prepared (translations or obsolete) | ||
* @returns {PreOutputTranslation[]|undefined} Prepared array | ||
*/ | ||
Compiler.prototype._prepareSection = function (section) { | ||
/** @type {GetTextTranslation[]} response Prepared array */ | ||
let response = []; | ||
|
||
for (const msgctxt in section) { | ||
if (typeof section[msgctxt] !== 'object') { | ||
return; | ||
} | ||
|
||
for (const msgid of Object.keys(section[msgctxt])) { | ||
if (typeof section[msgctxt][msgid] !== 'object') { | ||
continue; | ||
} | ||
|
||
if (msgctxt === '' && msgid === '') { | ||
continue; | ||
} | ||
|
||
response.push(section[msgctxt][msgid]); | ||
} | ||
} | ||
|
||
const { sort } = this._options; | ||
|
||
if (sort) { | ||
if (typeof sort === 'function') { | ||
response = response.sort(sort); | ||
} else { | ||
response = response.sort(compareMsgid); | ||
} | ||
} | ||
|
||
return response; | ||
}; | ||
|
||
/** | ||
* Compiles a translation object into a PO object | ||
* | ||
* @interface | ||
* @return {Buffer} Compiled a PO object | ||
*/ | ||
Compiler.prototype.compile = function () { | ||
if (!this._table.translations) { | ||
throw new Error('No translations found'); | ||
} | ||
/** @type {PreOutputTranslation} headerBlock */ | ||
const headerBlock = (this._table.translations[''] && this._table.translations['']['']) || {}; | ||
|
||
const translations = this._prepareSection(this._table.translations); | ||
let response = /** @type {(PreOutputTranslation|string)[]} */ (/** @type {unknown[]} */ (translations?.map(t => this._drawBlock(t)))); | ||
|
||
if (typeof this._table.obsolete === 'object') { | ||
const obsolete = this._prepareSection(this._table.obsolete); | ||
if (obsolete && obsolete.length) { | ||
response = response?.concat(obsolete.map(r => this._drawBlock(r, {}, true))); | ||
} | ||
} | ||
|
||
const eol = this._options.eol ?? '\n'; | ||
|
||
response?.unshift(this._drawBlock(headerBlock, { | ||
msgstr: generateHeader(this._table.headers) | ||
})); | ||
|
||
if (this._table.charset === 'utf-8' || this._table.charset === 'ascii') { | ||
return Buffer.from(response?.join(eol + eol) + eol, 'utf-8'); | ||
} | ||
|
||
return encoding.convert(response?.join(eol + eol) + eol, this._table.charset); | ||
}; |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/** | ||
* Represents a GetText comment. | ||
* @typedef {Object} GetTextComment | ||
* @property {string} [translator] Translator information. | ||
* @property {string} [reference] Reference information. | ||
* @property {string} [extracted] Extracted comments. | ||
* @property {string} [flag] Flags. | ||
* @property {string} [previous] Previous string. | ||
*/ | ||
|
||
/** | ||
* Represents a GetText translation. | ||
* @typedef {Object} GetTextTranslation | ||
* @property {string} [msgctxt] Context of the message. | ||
* @property {string} msgid The singular message ID. | ||
* @property {string} [msgid_plural] The plural message ID. | ||
* @property {string[]} msgstr Array of translated strings. | ||
* @property {GetTextComment} [comments] Comments associated with the translation. | ||
* @property {boolean} [obsolete] Whether the translation is obsolete. | ||
*/ | ||
|
||
/** | ||
* @typedef {Record<string, Record<string, GetTextTranslation>>} Translations The translations index. | ||
*/ | ||
|
||
/** | ||
* Represents GetText translations. | ||
* @typedef {Object} GetTextTranslations | ||
* @property {string|undefined} charset Character set. | ||
* @property {Record<string, string>} headers Headers. | ||
* @property {Translations} [obsolete] Obsolete messages. | ||
* @property {Translations} translations Translations. | ||
*/ | ||
|
||
/** | ||
* Options for the parser. | ||
* @typedef {Object} ParserOptions | ||
* @property {string} [defaultCharset] Default character set. | ||
* @property {boolean} [validation] Whether to perform validation. | ||
* @property {number} [foldLength] the fold length. | ||
* @property {boolean} [escapeCharacters] Whether to escape characters. | ||
* @property {boolean} [sort] Whether to sort messages. | ||
* @property {string} [eol] End of line character. | ||
*/ | ||
|
||
/** | ||
* @typedef {('writeUInt32LE'|'writeUInt32BE')} WriteFunc Type definition for write functions. | ||
*/ | ||
|
||
/** | ||
* @typedef {('readUInt32LE'|'readUInt32BE')} ReadFunc Type definition for read functions. | ||
*/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"compilerOptions": { | ||
"noImplicitAny": true, | ||
"removeComments": false, | ||
"module": "Node16", | ||
"moduleResolution": "Node16", | ||
"target": "ES2018", | ||
"lib": [ | ||
"ES2018" | ||
], | ||
// Strict mode | ||
"strict": true, | ||
// Allow javascript files | ||
"allowJs": true, | ||
// Check js files for errors | ||
"checkJs": true, | ||
// the directory sources are in | ||
"rootDir": "src", | ||
// Output d.ts files to @types | ||
"outDir": "lib", | ||
// Generate d.ts files | ||
"declaration": true, | ||
// Minify | ||
"pretty": false, | ||
// Skip lib check when compiling | ||
"skipLibCheck": true, | ||
// For providing missing package types | ||
"typeRoots": [ | ||
"./types", | ||
"./node_modules/@types" | ||
], | ||
}, | ||
"include": [ | ||
"src/**/*", | ||
"types/**/*" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
declare module 'encoding' { | ||
function convert(buffer: Buffer | string, charset?: string, fromCharset?: string): Buffer; | ||
} |
Uh oh!
There was an error while loading. Please reload this page.