mirror of https://github.com/ghostfolio/ghostfolio
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
7.0 KiB
257 lines
7.0 KiB
/**
|
|
* @license Angular v21.1.1
|
|
* (c) 2010-2026 Google LLC. https://angular.dev/
|
|
* License: MIT
|
|
*/
|
|
|
|
const BLOCK_MARKER$1 = ':';
|
|
const MEANING_SEPARATOR = '|';
|
|
const ID_SEPARATOR = '@@';
|
|
const LEGACY_ID_INDICATOR = '\u241F';
|
|
|
|
let textEncoder;
|
|
function fingerprint(str) {
|
|
textEncoder ??= new TextEncoder();
|
|
const utf8 = textEncoder.encode(str);
|
|
const view = new DataView(utf8.buffer, utf8.byteOffset, utf8.byteLength);
|
|
let hi = hash32(view, utf8.length, 0);
|
|
let lo = hash32(view, utf8.length, 102072);
|
|
if (hi == 0 && (lo == 0 || lo == 1)) {
|
|
hi = hi ^ 0x130f9bef;
|
|
lo = lo ^ -0x6b5f56d8;
|
|
}
|
|
return BigInt.asUintN(32, BigInt(hi)) << BigInt(32) | BigInt.asUintN(32, BigInt(lo));
|
|
}
|
|
function computeMsgId(msg, meaning = '') {
|
|
let msgFingerprint = fingerprint(msg);
|
|
if (meaning) {
|
|
msgFingerprint = BigInt.asUintN(64, msgFingerprint << BigInt(1)) | msgFingerprint >> BigInt(63) & BigInt(1);
|
|
msgFingerprint += fingerprint(meaning);
|
|
}
|
|
return BigInt.asUintN(63, msgFingerprint).toString();
|
|
}
|
|
function hash32(view, length, c) {
|
|
let a = 0x9e3779b9,
|
|
b = 0x9e3779b9;
|
|
let index = 0;
|
|
const end = length - 12;
|
|
for (; index <= end; index += 12) {
|
|
a += view.getUint32(index, true);
|
|
b += view.getUint32(index + 4, true);
|
|
c += view.getUint32(index + 8, true);
|
|
const res = mix(a, b, c);
|
|
a = res[0], b = res[1], c = res[2];
|
|
}
|
|
const remainder = length - index;
|
|
c += length;
|
|
if (remainder >= 4) {
|
|
a += view.getUint32(index, true);
|
|
index += 4;
|
|
if (remainder >= 8) {
|
|
b += view.getUint32(index, true);
|
|
index += 4;
|
|
if (remainder >= 9) {
|
|
c += view.getUint8(index++) << 8;
|
|
}
|
|
if (remainder >= 10) {
|
|
c += view.getUint8(index++) << 16;
|
|
}
|
|
if (remainder === 11) {
|
|
c += view.getUint8(index++) << 24;
|
|
}
|
|
} else {
|
|
if (remainder >= 5) {
|
|
b += view.getUint8(index++);
|
|
}
|
|
if (remainder >= 6) {
|
|
b += view.getUint8(index++) << 8;
|
|
}
|
|
if (remainder === 7) {
|
|
b += view.getUint8(index++) << 16;
|
|
}
|
|
}
|
|
} else {
|
|
if (remainder >= 1) {
|
|
a += view.getUint8(index++);
|
|
}
|
|
if (remainder >= 2) {
|
|
a += view.getUint8(index++) << 8;
|
|
}
|
|
if (remainder === 3) {
|
|
a += view.getUint8(index++) << 16;
|
|
}
|
|
}
|
|
return mix(a, b, c)[2];
|
|
}
|
|
function mix(a, b, c) {
|
|
a -= b;
|
|
a -= c;
|
|
a ^= c >>> 13;
|
|
b -= c;
|
|
b -= a;
|
|
b ^= a << 8;
|
|
c -= a;
|
|
c -= b;
|
|
c ^= b >>> 13;
|
|
a -= b;
|
|
a -= c;
|
|
a ^= c >>> 12;
|
|
b -= c;
|
|
b -= a;
|
|
b ^= a << 16;
|
|
c -= a;
|
|
c -= b;
|
|
c ^= b >>> 5;
|
|
a -= b;
|
|
a -= c;
|
|
a ^= c >>> 3;
|
|
b -= c;
|
|
b -= a;
|
|
b ^= a << 10;
|
|
c -= a;
|
|
c -= b;
|
|
c ^= b >>> 15;
|
|
return [a, b, c];
|
|
}
|
|
var Endian;
|
|
(function (Endian) {
|
|
Endian[Endian["Little"] = 0] = "Little";
|
|
Endian[Endian["Big"] = 1] = "Big";
|
|
})(Endian || (Endian = {}));
|
|
|
|
function parseMessage(messageParts, expressions, location, messagePartLocations, expressionLocations = []) {
|
|
const substitutions = {};
|
|
const substitutionLocations = {};
|
|
const associatedMessageIds = {};
|
|
const metadata = parseMetadata(messageParts[0], messageParts.raw[0]);
|
|
const cleanedMessageParts = [metadata.text];
|
|
const placeholderNames = [];
|
|
let messageString = metadata.text;
|
|
for (let i = 1; i < messageParts.length; i++) {
|
|
const {
|
|
messagePart,
|
|
placeholderName = computePlaceholderName(i),
|
|
associatedMessageId
|
|
} = parsePlaceholder(messageParts[i], messageParts.raw[i]);
|
|
messageString += `{$${placeholderName}}${messagePart}`;
|
|
if (expressions !== undefined) {
|
|
substitutions[placeholderName] = expressions[i - 1];
|
|
substitutionLocations[placeholderName] = expressionLocations[i - 1];
|
|
}
|
|
placeholderNames.push(placeholderName);
|
|
if (associatedMessageId !== undefined) {
|
|
associatedMessageIds[placeholderName] = associatedMessageId;
|
|
}
|
|
cleanedMessageParts.push(messagePart);
|
|
}
|
|
const messageId = metadata.customId || computeMsgId(messageString, metadata.meaning || '');
|
|
const legacyIds = metadata.legacyIds ? metadata.legacyIds.filter(id => id !== messageId) : [];
|
|
return {
|
|
id: messageId,
|
|
legacyIds,
|
|
substitutions,
|
|
substitutionLocations,
|
|
text: messageString,
|
|
customId: metadata.customId,
|
|
meaning: metadata.meaning || '',
|
|
description: metadata.description || '',
|
|
messageParts: cleanedMessageParts,
|
|
messagePartLocations,
|
|
placeholderNames,
|
|
associatedMessageIds,
|
|
location
|
|
};
|
|
}
|
|
function parseMetadata(cooked, raw) {
|
|
const {
|
|
text: messageString,
|
|
block
|
|
} = splitBlock(cooked, raw);
|
|
if (block === undefined) {
|
|
return {
|
|
text: messageString
|
|
};
|
|
} else {
|
|
const [meaningDescAndId, ...legacyIds] = block.split(LEGACY_ID_INDICATOR);
|
|
const [meaningAndDesc, customId] = meaningDescAndId.split(ID_SEPARATOR, 2);
|
|
let [meaning, description] = meaningAndDesc.split(MEANING_SEPARATOR, 2);
|
|
if (description === undefined) {
|
|
description = meaning;
|
|
meaning = undefined;
|
|
}
|
|
if (description === '') {
|
|
description = undefined;
|
|
}
|
|
return {
|
|
text: messageString,
|
|
meaning,
|
|
description,
|
|
customId,
|
|
legacyIds
|
|
};
|
|
}
|
|
}
|
|
function parsePlaceholder(cooked, raw) {
|
|
const {
|
|
text: messagePart,
|
|
block
|
|
} = splitBlock(cooked, raw);
|
|
if (block === undefined) {
|
|
return {
|
|
messagePart
|
|
};
|
|
} else {
|
|
const [placeholderName, associatedMessageId] = block.split(ID_SEPARATOR);
|
|
return {
|
|
messagePart,
|
|
placeholderName,
|
|
associatedMessageId
|
|
};
|
|
}
|
|
}
|
|
function splitBlock(cooked, raw) {
|
|
if (raw.charAt(0) !== BLOCK_MARKER$1) {
|
|
return {
|
|
text: cooked
|
|
};
|
|
} else {
|
|
const endOfBlock = findEndOfBlock(cooked, raw);
|
|
return {
|
|
block: cooked.substring(1, endOfBlock),
|
|
text: cooked.substring(endOfBlock + 1)
|
|
};
|
|
}
|
|
}
|
|
function computePlaceholderName(index) {
|
|
return index === 1 ? 'PH' : `PH_${index - 1}`;
|
|
}
|
|
function findEndOfBlock(cooked, raw) {
|
|
for (let cookedIndex = 1, rawIndex = 1; cookedIndex < cooked.length; cookedIndex++, rawIndex++) {
|
|
if (raw[rawIndex] === '\\') {
|
|
rawIndex++;
|
|
} else if (cooked[cookedIndex] === BLOCK_MARKER$1) {
|
|
return cookedIndex;
|
|
}
|
|
}
|
|
throw new Error(`Unterminated $localize metadata block in "${raw}".`);
|
|
}
|
|
|
|
const $localize = function (messageParts, ...expressions) {
|
|
if ($localize.translate) {
|
|
const translation = $localize.translate(messageParts, expressions);
|
|
messageParts = translation[0];
|
|
expressions = translation[1];
|
|
}
|
|
let message = stripBlock(messageParts[0], messageParts.raw[0]);
|
|
for (let i = 1; i < messageParts.length; i++) {
|
|
message += expressions[i - 1] + stripBlock(messageParts[i], messageParts.raw[i]);
|
|
}
|
|
return message;
|
|
};
|
|
const BLOCK_MARKER = ':';
|
|
function stripBlock(messagePart, rawMessagePart) {
|
|
return rawMessagePart.charAt(0) === BLOCK_MARKER ? messagePart.substring(findEndOfBlock(messagePart, rawMessagePart) + 1) : messagePart;
|
|
}
|
|
|
|
export { $localize, BLOCK_MARKER$1 as BLOCK_MARKER, computeMsgId, findEndOfBlock, parseMessage, parseMetadata, splitBlock };
|
|
//# sourceMappingURL=_localize-chunk.mjs.map
|
|
|