Socket
Socket
Sign inDemoInstall

messageformat

Package Overview
Dependencies
0
Maintainers
2
Versions
51
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.0.0-3.cf to 4.0.0-4

lib/parser/expression.d.ts

8

lib/data-model.d.ts
import type { MessageSyntaxError } from './errors';
import type { Junk, Literal, PatternElement, Placeholder, VariableRef } from './pattern';
import type { Junk, Literal, PatternElement, Expression, VariableRef } from './pattern';
/**

@@ -25,3 +25,3 @@ * The representation of a single message.

* A message may declare any number of local variables or aliases,
* each with a value defined by a placeholder.
* each with a value defined by an expression.
* The order of the declarations is not relevant,

@@ -34,3 +34,3 @@ * but a valid message may not include a dependency loop amond them.

target: VariableRef | Junk;
value: Placeholder | Junk;
value: Expression | Junk;
}

@@ -52,3 +52,3 @@ /**

* and selection between them is made according to
* the values of a corresponding number of placeholders.
* the values of a corresponding number of expressions.
* Selection iterates among the `variants` in order,

@@ -55,0 +55,0 @@ * and terminates when all of the Variant keys match.

export declare class MessageError extends Error {
type: 'junk-element' | 'missing-func' | 'unresolved-var' | typeof MessageSyntaxError.prototype.type;
type: 'junk-element' | 'missing-func' | 'reserved' | 'unresolved-var' | typeof MessageSyntaxError.prototype.type;
constructor(type: typeof MessageError.prototype.type, message: string);

@@ -4,0 +4,0 @@ }

@@ -7,3 +7,3 @@ "use strict";

for (const part of parts) {
if ((0, pattern_1.isExpression)(part)) {
if ((0, pattern_1.isFunctionRef)(part) && part.kind === 'value') {
if (typeof runtime[part.name] !== 'function') {

@@ -10,0 +10,0 @@ throw new ReferenceError(`Runtime function not available: ${part.name}`);

@@ -6,5 +6,5 @@ export { asMessageValue } from './as-message-value';

export { MessageLiteral } from './message-literal';
export { MessageMarkupStart, MessageMarkupEnd } from './message-markup';
export { MessageMarkup } from './message-markup';
export { MessageNumber } from './message-number';
export { MessageValue, Meta } from './message-value';
export { ResolvedMessage } from './resolved-message';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResolvedMessage = exports.MessageValue = exports.MessageNumber = exports.MessageMarkupEnd = exports.MessageMarkupStart = exports.MessageLiteral = exports.MessageFallback = exports.MessageDateTime = exports.extendLocaleContext = exports.asMessageValue = void 0;
exports.ResolvedMessage = exports.MessageValue = exports.MessageNumber = exports.MessageMarkup = exports.MessageLiteral = exports.MessageFallback = exports.MessageDateTime = exports.extendLocaleContext = exports.asMessageValue = void 0;
var as_message_value_1 = require("./as-message-value");

@@ -15,4 +15,3 @@ Object.defineProperty(exports, "asMessageValue", { enumerable: true, get: function () { return as_message_value_1.asMessageValue; } });

var message_markup_1 = require("./message-markup");
Object.defineProperty(exports, "MessageMarkupStart", { enumerable: true, get: function () { return message_markup_1.MessageMarkupStart; } });
Object.defineProperty(exports, "MessageMarkupEnd", { enumerable: true, get: function () { return message_markup_1.MessageMarkupEnd; } });
Object.defineProperty(exports, "MessageMarkup", { enumerable: true, get: function () { return message_markup_1.MessageMarkup; } });
var message_number_1 = require("./message-number");

@@ -19,0 +18,0 @@ Object.defineProperty(exports, "MessageNumber", { enumerable: true, get: function () { return message_number_1.MessageNumber; } });

@@ -8,6 +8,9 @@ import type { LocaleContextArg } from './locale-context';

*/
export declare class MessageMarkupStart extends MessageValue<string> {
export declare class MessageMarkup extends MessageValue<string> {
options: Record<string, unknown>;
constructor(locale: LocaleContextArg, name: string, { meta, options, source }: {
operand?: MessageValue;
constructor(locale: LocaleContextArg, name: string, { kind, meta, operand, options, source }: {
kind: 'open' | 'close';
meta?: Readonly<Meta>;
operand?: MessageValue;
options?: Readonly<Record<string, unknown>>;

@@ -19,14 +22,1 @@ source?: string;

}
/**
* A child class of {@link MessageValue} for ending markup elements.
*
* @beta
*/
export declare class MessageMarkupEnd extends MessageValue<string> {
constructor(locale: LocaleContextArg, name: string, options: {
meta?: Readonly<Meta>;
source?: string;
});
selectKey(): null;
toString(): string;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageMarkupEnd = exports.MessageMarkupStart = void 0;
exports.MessageMarkup = void 0;
const message_value_1 = require("./message-value");

@@ -12,6 +12,9 @@ const MARKUP_START = 'markup-start';

*/
class MessageMarkupStart extends message_value_1.MessageValue {
constructor(locale, name, { meta, options, source }) {
super(MARKUP_START, locale, name, { meta, source });
class MessageMarkup extends message_value_1.MessageValue {
constructor(locale, name, { kind, meta, operand, options, source }) {
const type = kind === 'open' ? MARKUP_START : MARKUP_END;
super(type, locale, name, { meta, source });
this.options = { ...options };
if (operand)
this.operand = operand;
}

@@ -22,22 +25,6 @@ selectKey() {

toString() {
return `{+${this.value}}`;
const sigil = this.type === MARKUP_START ? '+' : '-';
return `{${sigil}${this.value}}`;
}
}
exports.MessageMarkupStart = MessageMarkupStart;
/**
* A child class of {@link MessageValue} for ending markup elements.
*
* @beta
*/
class MessageMarkupEnd extends message_value_1.MessageValue {
constructor(locale, name, options) {
super(MARKUP_END, locale, name, options);
}
selectKey() {
return null;
}
toString() {
return `{-${this.value}}`;
}
}
exports.MessageMarkupEnd = MessageMarkupEnd;
exports.MessageMarkup = MessageMarkup;

@@ -31,3 +31,3 @@ import { Message } from './data-model';

resolvedOptions(): {
localeMatcher: "best fit" | "lookup";
localeMatcher: "lookup" | "best fit";
locales: string[];

@@ -34,0 +34,0 @@ message: Message;

import type { CatchallKey, Declaration, JunkMessage, Pattern, PatternMessage, SelectMessage, Variant } from '../data-model';
import type { MessageSyntaxError } from '../errors';
import type { Expression, Junk, Literal, MarkupEnd, MarkupStart, Option, Text, VariableRef } from '../pattern';
import type { Expression, FunctionRef, Junk, Literal, Option, Reserved, Text, VariableRef } from '../pattern';
export type MessageParsed = PatternMessageParsed | SelectMessageParsed | JunkMessageParsed;

@@ -14,3 +14,3 @@ export interface PatternMessageParsed extends PatternMessage {

declarations: DeclarationParsed[];
selectors: PlaceholderParsed[];
selectors: ExpressionParsed[];
variants: VariantParsed[];

@@ -30,3 +30,3 @@ errors: MessageSyntaxError[];

target: VariableRefParsed | JunkParsed;
value: PlaceholderParsed | JunkParsed;
value: ExpressionParsed | JunkParsed;
}

@@ -37,3 +37,3 @@ export interface VariantParsed extends Variant {

end: number;
keys: Array<LiteralParsed | NmtokenParsed | CatchallKeyParsed>;
keys: Array<LiteralParsed | LiteralParsed | CatchallKeyParsed>;
value: PatternParsed;

@@ -52,3 +52,3 @@ }

end: number;
body: Array<TextParsed | PlaceholderParsed>;
body: Array<TextParsed | ExpressionParsed>;
}

@@ -61,4 +61,4 @@ export interface TextParsed extends Text {

}
export interface PlaceholderParsed {
type: 'placeholder';
export interface ExpressionParsed extends Expression {
type: 'expression';
/** position of the `{` */

@@ -68,3 +68,3 @@ start: number;

end: number;
body: LiteralParsed | VariableRefParsed | ExpressionParsed | MarkupStartParsed | MarkupEndParsed | JunkParsed;
body: LiteralParsed | VariableRefParsed | FunctionRefParsed | ReservedParsed | JunkParsed;
}

@@ -79,2 +79,3 @@ export interface JunkParsed extends Junk {

type: 'literal';
quoted: boolean;
/** position of the initial `|` */

@@ -93,6 +94,7 @@ start: number;

}
export interface ExpressionParsed extends Expression {
type: 'expression';
export interface FunctionRefParsed extends FunctionRef {
type: 'function';
kind: 'open' | 'close' | 'value';
operand: LiteralParsed | VariableRefParsed | undefined;
/** position of the `:`, so `operand.start` may be earlier */
/** position of the `:`/`+`/`-`, so `operand.start` may be earlier */
start: number;

@@ -103,17 +105,11 @@ end: number;

}
export interface MarkupStartParsed extends MarkupStart {
type: 'markup-start';
/** position of the `+` */
export interface ReservedParsed extends Reserved {
type: 'reserved';
sigil: '!' | '@' | '#' | '%' | '^' | '&' | '*' | '<' | '>' | '?' | '~';
operand: Literal | VariableRef | undefined;
source: string;
/** position of the sigil, so `operand.start` may be earlier */
start: number;
end: number;
name: string;
options: OptionParsed[];
}
export interface MarkupEndParsed extends MarkupEnd {
type: 'markup-end';
/** position of the `-` */
start: number;
end: number;
name: string;
}
export interface OptionParsed extends Option {

@@ -124,10 +120,3 @@ /** position at the start of the name */

name: string;
value: LiteralParsed | NmtokenParsed | VariableRefParsed;
value: LiteralParsed | LiteralParsed | VariableRefParsed;
}
export interface NmtokenParsed extends Literal {
type: 'nmtoken';
/** position at the start of the value */
start: number;
end: number;
value: string;
}

@@ -1,6 +0,6 @@

import { MessageSyntaxError } from '../errors.js';
import type { DeclarationParsed } from './data-model.js';
export declare function parseDeclarations(src: string, errors: MessageSyntaxError[]): {
import type { ParseContext } from './message.js';
export declare function parseDeclarations(ctx: ParseContext): {
declarations: DeclarationParsed[];
end: number;
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseDeclarations = void 0;
const errors_js_1 = require("../errors.js");
const placeholder_js_1 = require("./placeholder.js");
const expression_js_1 = require("./expression.js");
const util_js_1 = require("./util.js");
const values_js_1 = require("./values.js");
// Declaration ::= 'let' WhiteSpace Variable '=' '{' Expression '}'
function parseDeclarations(src, errors) {
let pos = (0, util_js_1.whitespaces)(src, 0);
function parseDeclarations(ctx) {
let pos = (0, util_js_1.whitespaces)(ctx.source, 0);
const declarations = [];
while (src.startsWith('let', pos)) {
const decl = parseDeclaration(src, pos, errors);
while (ctx.source.startsWith('let', pos)) {
const decl = parseDeclaration(ctx, pos);
declarations.push(decl);
pos = decl.end;
pos += (0, util_js_1.whitespaces)(src, pos);
pos += (0, util_js_1.whitespaces)(ctx.source, pos);
}
checkLocalVarReferences(declarations, errors);
checkLocalVarReferences(ctx, declarations);
return { declarations, end: pos };
}
exports.parseDeclarations = parseDeclarations;
function parseDeclaration(src, start, errors) {
// declaration = let s variable [s] "=" [s] expression
// let = %x6C.65.74 ; "let"
function parseDeclaration(ctx, start) {
let pos = start + 3; // 'let'
const ws = (0, util_js_1.whitespaces)(src, pos);
const ws = (0, util_js_1.whitespaces)(ctx.source, pos);
pos += ws;
if (ws === 0)
errors.push(new errors_js_1.MissingCharError(pos, ' '));
ctx.onError('missing-char', pos, ' ');
let target;
if (src[pos] === '$') {
target = (0, values_js_1.parseVariable)(src, pos, errors);
if (ctx.source[pos] === '$') {
target = (0, values_js_1.parseVariable)(ctx, pos);
pos = target.end;

@@ -35,4 +35,4 @@ }

const junkStart = pos;
const junkEndOffset = src.substring(pos).search(/[\t\n\r ={}]/);
pos = junkEndOffset === -1 ? src.length : pos + junkEndOffset;
const junkEndOffset = ctx.source.substring(pos).search(/[\t\n\r ={}]/);
pos = junkEndOffset === -1 ? ctx.source.length : pos + junkEndOffset;
target = {

@@ -42,15 +42,15 @@ type: 'junk',

end: pos,
source: src.substring(junkStart, pos)
source: ctx.source.substring(junkStart, pos)
};
errors.push(new errors_js_1.MissingCharError(junkStart, '$'));
ctx.onError('missing-char', junkStart, '$');
}
pos += (0, util_js_1.whitespaces)(src, pos);
if (src[pos] === '=')
pos += (0, util_js_1.whitespaces)(ctx.source, pos);
if (ctx.source[pos] === '=')
pos += 1;
else
errors.push(new errors_js_1.MissingCharError(pos, '='));
ctx.onError('missing-char', pos, '=');
let value;
pos += (0, util_js_1.whitespaces)(src, pos);
if (src[pos] === '{') {
value = (0, placeholder_js_1.parsePlaceholder)(src, pos, errors);
pos += (0, util_js_1.whitespaces)(ctx.source, pos);
if (ctx.source[pos] === '{') {
value = (0, expression_js_1.parseExpression)(ctx, pos);
pos = value.end;

@@ -60,6 +60,6 @@ }

const junkStart = pos;
const junkEndOffset = src
const junkEndOffset = ctx.source
.substring(pos)
.search(/\blet|\bmatch|\bwhen|[${}]/);
pos = junkEndOffset === -1 ? src.length : pos + junkEndOffset;
pos = junkEndOffset === -1 ? ctx.source.length : pos + junkEndOffset;
value = {

@@ -69,5 +69,5 @@ type: 'junk',

end: pos,
source: src.substring(junkStart, pos)
source: ctx.source.substring(junkStart, pos)
};
errors.push(new errors_js_1.MissingCharError(junkStart, '{'));
ctx.onError('missing-char', junkStart, '{');
}

@@ -77,6 +77,6 @@ return { start, end: pos, target, value };

/** Local variable declarations can't refer to later ones */
function checkLocalVarReferences(declarations, errors) {
function checkLocalVarReferences(ctx, declarations) {
const check = (name, ref) => {
if (ref.name === name) {
errors.push(new errors_js_1.MessageSyntaxError('bad-local-var', ref.start, ref.end));
ctx.onError('bad-local-var', ref.start, ref.end);
}

@@ -90,6 +90,6 @@ };

const ph = declarations[j].value;
if (ph.type === 'placeholder') {
if (ph.type === 'expression') {
const exp = ph.body;
switch (exp.type) {
case 'expression':
case 'function':
if (exp.operand?.type === 'variable')

@@ -96,0 +96,0 @@ check(name, exp.operand);

@@ -0,2 +1,13 @@

import { MessageSyntaxError } from '../errors.js';
import type { MessageParsed } from './data-model.js';
export declare class ParseContext {
readonly errors: MessageSyntaxError[];
readonly resource: boolean;
readonly source: string;
constructor(source: string, opt?: {
resource?: boolean;
});
onError(type: Exclude<typeof MessageSyntaxError.prototype.type, 'missing-char'>, start: number, end: number): void;
onError(type: 'missing-char', start: number, char: string): void;
}
/**

@@ -8,2 +19,4 @@ * Parse the string syntax representation of a message into

*/
export declare function parseMessage(src: string): MessageParsed;
export declare function parseMessage(source: string, opt?: {
resource?: boolean;
}): MessageParsed;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseMessage = void 0;
exports.parseMessage = exports.ParseContext = void 0;
const errors_js_1 = require("../errors.js");
const declarations_js_1 = require("./declarations.js");
const names_js_1 = require("./names.js");
const placeholder_js_1 = require("./placeholder.js");
const expression_js_1 = require("./expression.js");
const util_js_1 = require("./util.js");
const values_js_1 = require("./values.js");
// Message ::= Declaration* ( Pattern | Selector Variant+ )
// Selector ::= 'match' ( '{' Expression '}' )+
class ParseContext {
constructor(source, opt) {
this.errors = [];
this.resource = opt?.resource ?? false;
this.source = source;
}
onError(type, start, end) {
let err;
switch (type) {
case 'key-mismatch':
case 'missing-fallback':
err = new errors_js_1.MessageDataModelError(type, start, Number(end));
break;
case 'missing-char':
err = new errors_js_1.MissingCharError(start, String(end));
break;
default:
err = new errors_js_1.MessageSyntaxError(type, start, Number(end));
}
this.errors.push(err);
}
}
exports.ParseContext = ParseContext;
// message = [s] *(declaration [s]) body [s]
// body = pattern / (selectors 1*([s] variant))
// selectors = match 1*([s] expression)
/**

@@ -18,34 +41,34 @@ * Parse the string syntax representation of a message into

*/
function parseMessage(src) {
const errors = [];
const { declarations, end: pos } = (0, declarations_js_1.parseDeclarations)(src, errors);
if (src.startsWith('match', pos)) {
return parseSelectMessage(src, pos, declarations, errors);
function parseMessage(source, opt) {
const ctx = new ParseContext(source, opt);
const { declarations, end: pos } = (0, declarations_js_1.parseDeclarations)(ctx);
if (source.startsWith('match', pos)) {
return parseSelectMessage(ctx, pos, declarations);
}
else if (src[pos] === '{') {
return parsePatternMessage(src, pos, declarations, errors);
else if (source[pos] === '{') {
return parsePatternMessage(ctx, pos, declarations);
}
else {
errors.push(new errors_js_1.MessageSyntaxError('parse-error', pos, src.length));
return { type: 'junk', declarations, errors, source: src };
ctx.onError('parse-error', pos, source.length);
return { type: 'junk', declarations, errors: ctx.errors, source };
}
}
exports.parseMessage = parseMessage;
function parsePatternMessage(src, start, declarations, errors) {
const pattern = parsePattern(src, start, errors);
function parsePatternMessage(ctx, start, declarations) {
const pattern = parsePattern(ctx, start);
let pos = pattern.end;
pos += (0, util_js_1.whitespaces)(src, pos);
if (pos < src.length) {
errors.push(new errors_js_1.MessageSyntaxError('extra-content', pos, src.length));
pos += (0, util_js_1.whitespaces)(ctx.source, pos);
if (pos < ctx.source.length) {
ctx.onError('extra-content', pos, ctx.source.length);
}
return { type: 'message', declarations, pattern, errors };
return { type: 'message', declarations, pattern, errors: ctx.errors };
}
function parseSelectMessage(src, start, declarations, errors) {
function parseSelectMessage(ctx, start, declarations) {
let pos = start + 5; // 'match'
pos += (0, util_js_1.whitespaces)(src, pos);
pos += (0, util_js_1.whitespaces)(ctx.source, pos);
const selectors = [];
while (src[pos] === '{') {
const ph = (0, placeholder_js_1.parsePlaceholder)(src, pos, errors);
while (ctx.source[pos] === '{') {
const ph = (0, expression_js_1.parseExpression)(ctx, pos);
switch (ph.body.type) {
case 'expression':
case 'function':
case 'literal':

@@ -56,3 +79,3 @@ case 'variable':

const { start, end } = ph.body;
errors.push(new errors_js_1.MessageSyntaxError('bad-selector', start, end));
ctx.onError('bad-selector', start, end);
}

@@ -62,44 +85,42 @@ }

pos = ph.end;
pos += (0, util_js_1.whitespaces)(src, pos);
pos += (0, util_js_1.whitespaces)(ctx.source, pos);
}
if (selectors.length === 0) {
errors.push(new errors_js_1.MessageSyntaxError('empty-token', pos, pos + 1));
ctx.onError('empty-token', pos, pos + 1);
}
const variants = [];
pos += (0, util_js_1.whitespaces)(src, pos);
while (src.startsWith('when', pos)) {
const variant = parseVariant(src, pos, selectors.length, errors);
pos += (0, util_js_1.whitespaces)(ctx.source, pos);
while (ctx.source.startsWith('when', pos)) {
const variant = parseVariant(ctx, pos, selectors.length);
variants.push(variant);
pos = variant.end;
pos += (0, util_js_1.whitespaces)(src, pos);
pos += (0, util_js_1.whitespaces)(ctx.source, pos);
}
if (pos < src.length) {
errors.push(new errors_js_1.MessageSyntaxError('extra-content', pos, src.length));
if (pos < ctx.source.length) {
ctx.onError('extra-content', pos, ctx.source.length);
}
return { type: 'select', declarations, selectors, variants, errors };
return {
type: 'select',
declarations,
selectors,
variants,
errors: ctx.errors
};
}
// Variant ::= 'when' ( WhiteSpace VariantKey )+ Pattern
// VariantKey ::= Literal | Nmtoken | '*'
function parseVariant(src, start, selCount, errors) {
// variant = when 1*(s key) [s] pattern
// key = literal / "*"
function parseVariant(ctx, start, selCount) {
let pos = start + 4; // 'when'
const keys = [];
while (pos < src.length) {
const ws = (0, util_js_1.whitespaces)(src, pos);
while (pos < ctx.source.length) {
const ws = (0, util_js_1.whitespaces)(ctx.source, pos);
pos += ws;
const ch = src[pos];
const ch = ctx.source[pos];
if (ch === '{')
break;
if (ws === 0)
errors.push(new errors_js_1.MissingCharError(pos, ' '));
let key;
switch (ch) {
case '*':
key = { type: '*', start: pos, end: pos + 1 };
break;
case '|':
key = (0, values_js_1.parseLiteral)(src, pos, errors);
break;
default:
key = (0, names_js_1.parseNmtoken)(src, pos, errors);
}
ctx.onError('missing-char', pos, ' ');
const key = ch === '*'
? ({ type: '*', start: pos, end: pos + 1 })
: (0, values_js_1.parseLiteral)(ctx, pos, true);
if (key.end === pos)

@@ -112,11 +133,11 @@ break; // error; reported in pattern.errors

const end = keys.length === 0 ? pos : keys[keys.length - 1].end;
errors.push(new errors_js_1.MessageDataModelError('key-mismatch', start, end));
ctx.onError('key-mismatch', start, end);
}
const value = parsePattern(src, pos, errors);
const value = parsePattern(ctx, pos);
return { start, end: value.end, keys, value };
}
// Pattern ::= '{' (Text | Placeholder)* '}' /* ws: explicit */
function parsePattern(src, start, errors) {
if (src[start] !== '{') {
errors.push(new errors_js_1.MissingCharError(start, '{'));
// pattern = "{" *(text / expression) "}"
function parsePattern(ctx, start) {
if (ctx.source[start] !== '{') {
ctx.onError('missing-char', start, '{');
return { start, end: start, body: [] };

@@ -126,6 +147,6 @@ }

const body = [];
loop: while (pos < src.length) {
switch (src[pos]) {
loop: while (pos < ctx.source.length) {
switch (ctx.source[pos]) {
case '{': {
const ph = (0, placeholder_js_1.parsePlaceholder)(src, pos, errors);
const ph = (0, expression_js_1.parseExpression)(ctx, pos);
body.push(ph);

@@ -138,3 +159,3 @@ pos = ph.end;

default: {
const tx = (0, values_js_1.parseText)(src, pos, errors);
const tx = (0, values_js_1.parseText)(ctx, pos);
body.push(tx);

@@ -145,7 +166,7 @@ pos = tx.end;

}
if (src[pos] === '}')
if (ctx.source[pos] === '}')
pos += 1;
else
errors.push(new errors_js_1.MissingCharError(pos, '}'));
ctx.onError('missing-char', pos, '}');
return { start, end: pos, body };
}

@@ -1,5 +0,4 @@

import { MessageSyntaxError } from '../errors.js';
import type { NmtokenParsed } from './data-model.js';
export declare function isValidNmtoken(str: string): boolean;
import type { ParseContext } from './message.js';
export declare function isValidUnquotedLiteral(str: string): boolean;
export declare function parseNameValue(src: string, start: number): string;
export declare function parseNmtoken(src: string, start: number, errors: MessageSyntaxError[]): NmtokenParsed;
export declare function parseUnquotedLiteralValue(ctx: ParseContext, start: number): string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseNmtoken = exports.parseNameValue = exports.isValidNmtoken = void 0;
const errors_js_1 = require("../errors.js");
// NameStart ::= [a-zA-Z] | "_"
// | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF]
// | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D]
// | [#x2070-#x218F]
// | [#x2C00-#x2FEF]
// | [#x3001-#xD7FF]
// | [#xF900-#xFDCF]
// | [#xFDF0-#xFFFD]
// | [#x10000-#xEFFFF]
exports.parseUnquotedLiteralValue = exports.parseNameValue = exports.isValidUnquotedLiteral = void 0;
// name-start = ALPHA / "_"
// / %xC0-D6 / %xD8-F6 / %xF8-2FF
// / %x370-37D / %x37F-1FFF / %x200C-200D
// / %x2070-218F / %x2C00-2FEF / %x3001-D7FF
// / %xF900-FDCF / %xFDF0-FFFD / %x10000-EFFFF
const isNameStartCode = (cc) => (cc >= 0x41 && cc <= 0x5a) || // A-Z

@@ -29,6 +24,5 @@ cc === 0x5f || // _

(cc >= 0x10000 && cc <= 0xeffff);
// NameChar ::= NameStart | [0-9] | "-" | "." | #xB7
// | [#x0300-#x036F] | [#x203F-#x2040]
const isNameCharCode = (cc) => isNameStartCode(cc) ||
cc === 0x2d || // -
// unquoted-start = name-start / DIGIT / "."
// / %xB7 / %x300-36F / %x203F-2040
const isUnquotedStartCharCode = (cc) => isNameStartCode(cc) ||
cc === 0x2e || // .

@@ -40,4 +34,9 @@ (cc >= 0x30 && cc <= 0x39) || // 0-9

cc === 0x2040; // ⁀
function isValidNmtoken(str) {
for (let i = 0; i < str.length; ++i) {
// name-char = name-start / DIGIT / "-" / "." / ":"
// / %xB7 / %x300-36F / %x203F-2040
const isNameCharCode = (cc) => isUnquotedStartCharCode(cc) || cc === 0x2d || cc === 0x3a; // - :
function isValidUnquotedLiteral(str) {
if (!isUnquotedStartCharCode(str.charCodeAt(0)))
return false;
for (let i = 1; i < str.length; ++i) {
const cc = str.charCodeAt(i);

@@ -49,4 +48,4 @@ if (!isNameCharCode(cc))

}
exports.isValidNmtoken = isValidNmtoken;
// Name ::= NameStart NameChar* /* ws: explicit */
exports.isValidUnquotedLiteral = isValidUnquotedLiteral;
// name = name-start *name-char
function parseNameValue(src, start) {

@@ -61,13 +60,12 @@ if (!isNameStartCode(src.charCodeAt(start)))

exports.parseNameValue = parseNameValue;
// Nmtoken ::= NameChar+ /* ws: explicit */
function parseNmtoken(src, start, errors) {
// unquoted = unquoted-start *name-char
function parseUnquotedLiteralValue(ctx, start) {
let pos = start;
while (isNameCharCode(src.charCodeAt(pos)))
if (isUnquotedStartCharCode(ctx.source.charCodeAt(pos))) {
pos += 1;
const value = src.substring(start, pos);
if (!value) {
errors.push(new errors_js_1.MessageSyntaxError('empty-token', start, start + 1));
while (isNameCharCode(ctx.source.charCodeAt(pos)))
pos += 1;
}
return { type: 'nmtoken', start, end: pos, value };
return ctx.source.substring(start, pos);
}
exports.parseNmtoken = parseNmtoken;
exports.parseUnquotedLiteralValue = parseUnquotedLiteralValue;

@@ -1,5 +0,7 @@

import { MessageSyntaxError } from '../errors.js';
import type { LiteralParsed, TextParsed, VariableRefParsed } from './data-model.js';
export declare function parseText(src: string, start: number, errors: MessageSyntaxError[]): TextParsed;
export declare function parseLiteral(src: string, start: number, errors: MessageSyntaxError[]): LiteralParsed;
export declare function parseVariable(src: string, start: number, errors: MessageSyntaxError[]): VariableRefParsed;
import type { ParseContext } from './message.js';
export declare function parseText(ctx: ParseContext, start: number): TextParsed;
export declare function parseLiteral(ctx: ParseContext, start: number, required: true): LiteralParsed;
export declare function parseLiteral(ctx: ParseContext, start: number, required: boolean): LiteralParsed | undefined;
export declare function parseQuotedLiteral(ctx: ParseContext, start: number): LiteralParsed;
export declare function parseVariable(ctx: ParseContext, start: number): VariableRefParsed;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseVariable = exports.parseLiteral = exports.parseText = void 0;
const errors_js_1 = require("../errors.js");
exports.parseVariable = exports.parseQuotedLiteral = exports.parseLiteral = exports.parseText = void 0;
const names_js_1 = require("./names.js");

@@ -11,18 +10,15 @@ // Text ::= (TextChar | TextEscape)+

// TextEscape ::= Esc Esc | Esc '{' | Esc '}'
function parseText(src, start, errors) {
function parseText(ctx, start) {
let value = '';
let pos = start;
let i = start;
loop: for (; i < src.length; ++i) {
switch (src[i]) {
loop: for (; i < ctx.source.length; ++i) {
switch (ctx.source[i]) {
case '\\': {
const esc = src[i + 1];
if (esc !== '\\' && esc !== '{' && esc !== '}') {
errors.push(new errors_js_1.MessageSyntaxError('bad-escape', i, i + 2));
const esc = parseEscape(ctx, 'text', i);
if (esc) {
value += ctx.source.substring(pos, i) + esc.value;
i += esc.length;
pos = i + 1;
}
else {
value += src.slice(pos, i);
i += 1;
pos = i;
}
break;

@@ -33,48 +29,148 @@ }

break loop;
case '\n':
if (ctx.resource) {
const nl = i;
let next = ctx.source[i + 1];
while (next === ' ' || next === '\t') {
i += 1;
next = ctx.source[i + 1];
}
if (i > nl) {
value += ctx.source.substring(pos, nl + 1);
pos = i + 1;
}
}
break;
}
}
value += src.slice(pos, i);
value += ctx.source.substring(pos, i);
return { type: 'text', start, end: i, value };
}
exports.parseText = parseText;
// Literal ::= '(' (LiteralChar | LiteralEscape)* ')' /* ws: explicit */
// Esc ::= '\'
// LiteralChar ::= AnyChar - ('|' | Esc)
// LiteralEscape ::= Esc Esc | Esc '|'
function parseLiteral(src, start, errors) {
function parseLiteral(ctx, start, required) {
if (ctx.source[start] === '|')
return parseQuotedLiteral(ctx, start);
const value = (0, names_js_1.parseUnquotedLiteralValue)(ctx, start);
if (!value) {
if (required)
ctx.onError('empty-token', start, start);
else
return undefined;
}
const end = start + value.length;
return { type: 'literal', quoted: false, start, end, value };
}
exports.parseLiteral = parseLiteral;
// quoted = "|" *(quoted-char / quoted-escape) "|"
// quoted-char = %x0-5B ; omit \
// / %x5D-7B ; omit |
// / %x7D-D7FF ; omit surrogates
// / %xE000-10FFFF
// quoted-escape = backslash ( backslash / "|" )
// backslash = %x5C ; U+005C REVERSE SOLIDUS "\"
function parseQuotedLiteral(ctx, start) {
let value = '';
let pos = start + 1;
for (let i = pos; i < src.length; ++i) {
switch (src[i]) {
for (let i = pos; i < ctx.source.length; ++i) {
switch (ctx.source[i]) {
case '\\': {
const esc = src[i + 1];
if (esc !== '\\' && esc !== '|') {
errors.push(new errors_js_1.MessageSyntaxError('bad-escape', i, i + 2));
const esc = parseEscape(ctx, 'literal', i);
if (esc) {
value += ctx.source.substring(pos, i) + esc.value;
i += esc.length;
pos = i + 1;
}
else {
value += src.substring(pos, i);
i += 1;
pos = i;
}
break;
}
case '|':
value += src.substring(pos, i);
return { type: 'literal', start, end: i + 1, value };
value += ctx.source.substring(pos, i);
return { type: 'literal', quoted: true, start, end: i + 1, value };
case '\n':
if (ctx.resource) {
const nl = i;
let next = ctx.source[i + 1];
while (next === ' ' || next === '\t') {
i += 1;
next = ctx.source[i + 1];
}
if (i > nl) {
value += ctx.source.substring(pos, nl + 1);
pos = i + 1;
}
}
break;
}
}
value += src.substring(pos);
errors.push(new errors_js_1.MissingCharError(src.length, '|'));
return { type: 'literal', start, end: src.length, value };
value += ctx.source.substring(pos);
ctx.onError('missing-char', ctx.source.length, '|');
return {
type: 'literal',
quoted: true,
start,
end: ctx.source.length,
value
};
}
exports.parseLiteral = parseLiteral;
exports.parseQuotedLiteral = parseQuotedLiteral;
// Variable ::= '$' Name /* ws: explicit */
function parseVariable(src, start, errors) {
function parseVariable(ctx, start) {
const pos = start + 1;
const name = (0, names_js_1.parseNameValue)(src, pos);
const name = (0, names_js_1.parseNameValue)(ctx.source, pos);
const end = pos + name.length;
if (!name)
errors.push(new errors_js_1.MessageSyntaxError('empty-token', pos, pos + 1));
ctx.onError('empty-token', pos, pos + 1);
return { type: 'variable', start, end, name };
}
exports.parseVariable = parseVariable;
function parseEscape(ctx, scope, start) {
const raw = ctx.source[start + 1];
switch (raw) {
case '\\':
return { value: raw, length: 1 };
case '{':
case '}':
if (scope === 'text')
return { value: raw, length: 1 };
break;
case '|':
if (scope === 'literal')
return { value: raw, length: 1 };
break;
default:
if (ctx.resource) {
let hexLen = 0;
switch (raw) {
case '\t':
case ' ':
return { value: raw, length: 1 };
case 'n':
return { value: '\n', length: 1 };
case 'r':
return { value: '\r', length: 1 };
case 't':
return { value: '\t', length: 1 };
case 'u':
hexLen = 4;
break;
case 'U':
hexLen = 6;
break;
case 'x':
hexLen = 2;
break;
}
if (hexLen > 0) {
const h0 = start + 2;
const raw = ctx.source.substring(h0, h0 + hexLen);
if (raw.length === hexLen && /^[0-9A-Fa-f]+$/.test(raw)) {
return {
value: String.fromCharCode(parseInt(raw, 16)),
length: 1 + hexLen
};
}
}
}
}
ctx.onError('bad-escape', start, start + 2);
return null;
}
import type { Context } from '../format-context';
import type { MessageValue } from '../message-value';
import { Expression } from './expression';
import { FunctionRef } from './function-ref';
import { Junk } from './junk';
import { Literal, Text } from './literal';
import { MarkupEnd, MarkupStart } from './markup';
import { Reserved } from './reserved';
import { VariableRef } from './variable-ref';
export { isExpression, Expression, Option } from './expression';
export { isFunctionRef, FunctionRef, Option } from './function-ref';
export { isJunk, Junk } from './junk';
export { isLiteral, isText, Literal, Text } from './literal';
export { isMarkupEnd, isMarkupStart, MarkupEnd, MarkupStart } from './markup';
export { isReserved, Reserved } from './reserved';
export { isVariableRef, VariableRef } from './variable-ref';

@@ -18,12 +18,12 @@ /**

*/
export interface Placeholder {
type: 'placeholder';
body: Literal | VariableRef | Expression | MarkupStart | MarkupEnd | Junk;
export interface Expression {
type: 'expression';
body: Literal | VariableRef | FunctionRef | Reserved | Junk;
}
/**
* Type guard for {@link Placeholder} pattern elements
* Type guard for {@link Expression} pattern elements
*
* @beta
*/
export declare const isPlaceholder: (part: any) => part is Placeholder;
export declare const isExpression: (part: any) => part is Expression;
/**

@@ -36,8 +36,8 @@ * The contents of a message are a sequence of pattern elements, which may be

* @remarks
* Depending on the syntax, pattern elements may be wrapped within a Placeholder.
* Depending on the syntax, pattern elements may be wrapped within an Expression.
*
* @beta
*/
export type PatternElement = Expression | Junk | Literal | MarkupEnd | MarkupStart | Placeholder | Text | VariableRef;
export type PatternElement = Expression | FunctionRef | Junk | Literal | Reserved | Text | VariableRef;
/** @internal */
export declare function resolvePatternElement(ctx: Context, elem: PatternElement): MessageValue;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolvePatternElement = exports.isPlaceholder = exports.isVariableRef = exports.isMarkupStart = exports.isMarkupEnd = exports.isText = exports.isLiteral = exports.isJunk = exports.isExpression = void 0;
const expression_1 = require("./expression");
exports.resolvePatternElement = exports.isExpression = exports.isVariableRef = exports.isReserved = exports.isText = exports.isLiteral = exports.isJunk = exports.isFunctionRef = void 0;
const function_ref_1 = require("./function-ref");
const junk_1 = require("./junk");
const literal_1 = require("./literal");
const markup_1 = require("./markup");
const reserved_1 = require("./reserved");
const variable_ref_1 = require("./variable-ref");
var expression_2 = require("./expression");
Object.defineProperty(exports, "isExpression", { enumerable: true, get: function () { return expression_2.isExpression; } });
var function_ref_2 = require("./function-ref");
Object.defineProperty(exports, "isFunctionRef", { enumerable: true, get: function () { return function_ref_2.isFunctionRef; } });
var junk_2 = require("./junk");

@@ -16,9 +16,8 @@ Object.defineProperty(exports, "isJunk", { enumerable: true, get: function () { return junk_2.isJunk; } });

Object.defineProperty(exports, "isText", { enumerable: true, get: function () { return literal_2.isText; } });
var markup_2 = require("./markup");
Object.defineProperty(exports, "isMarkupEnd", { enumerable: true, get: function () { return markup_2.isMarkupEnd; } });
Object.defineProperty(exports, "isMarkupStart", { enumerable: true, get: function () { return markup_2.isMarkupStart; } });
var reserved_2 = require("./reserved");
Object.defineProperty(exports, "isReserved", { enumerable: true, get: function () { return reserved_2.isReserved; } });
var variable_ref_2 = require("./variable-ref");
Object.defineProperty(exports, "isVariableRef", { enumerable: true, get: function () { return variable_ref_2.isVariableRef; } });
/**
* Type guard for {@link Placeholder} pattern elements
* Type guard for {@link Expression} pattern elements
*

@@ -28,4 +27,4 @@ * @beta

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isPlaceholder = (part) => !!part && typeof part === 'object' && part.type === 'placeholder';
exports.isPlaceholder = isPlaceholder;
const isExpression = (part) => !!part && typeof part === 'object' && part.type === 'expression';
exports.isExpression = isExpression;
/** @internal */

@@ -35,15 +34,12 @@ function resolvePatternElement(ctx, elem) {

case 'literal':
case 'nmtoken':
case 'text':
return (0, literal_1.resolveLiteral)(elem);
case 'placeholder':
case 'expression':
return resolvePatternElement(ctx, elem.body);
case 'variable':
return (0, variable_ref_1.resolveVariableRef)(ctx, elem);
case 'expression':
return (0, expression_1.resolveExpression)(ctx, elem);
case 'markup-start':
return (0, markup_1.resolveMarkupStart)(ctx, elem);
case 'markup-end':
return (0, markup_1.resolveMarkupEnd)(ctx, elem);
case 'function':
return (0, function_ref_1.resolveFunctionRef)(ctx, elem);
case 'reserved':
return (0, reserved_1.resolveReserved)(ctx, elem);
case 'junk':

@@ -50,0 +46,0 @@ return (0, junk_1.resolveJunk)(ctx, elem);

@@ -13,3 +13,4 @@ import { MessageLiteral } from '../message-value';

export interface Literal {
type: 'literal' | 'nmtoken';
type: 'literal';
quoted: boolean;
value: string;

@@ -16,0 +17,0 @@ }

@@ -11,5 +11,3 @@ "use strict";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isLiteral = (part) => !!part &&
typeof part === 'object' &&
(part.type === 'literal' || part.type === 'nmtoken');
const isLiteral = (part) => !!part && typeof part === 'object' && part.type === 'literal';
exports.isLiteral = isLiteral;

@@ -16,0 +14,0 @@ /**

@@ -25,3 +25,3 @@ import { MessageValue } from '../message-value';

/**
* The runtime function registry available when resolving {@link Expression} elements.
* The runtime function registry available when resolving {@link FunctionRef} elements.
*

@@ -28,0 +28,0 @@ * @beta

@@ -8,2 +8,3 @@ "use strict";

const pattern_1 = require("../pattern");
const function_ref_1 = require("../pattern/function-ref");
/**

@@ -26,3 +27,3 @@ * Stringify a message using its syntax representation.

for (const sel of msg.selectors)
res += ' ' + stringifyPlaceholder(sel);
res += ' ' + stringifyExpression(sel);
for (const { keys, value } of msg.variants) {

@@ -46,8 +47,8 @@ res += '\nwhen ';

: stringifyJunk(target);
const valueStr = (0, pattern_1.isPlaceholder)(value)
? stringifyPlaceholder(value)
const valueStr = (0, pattern_1.isExpression)(value)
? stringifyExpression(value)
: stringifyJunk(value);
return `let ${targetStr} = ${valueStr}\n`;
}
function stringifyExpression({ name, operand, options }) {
function stringifyFunctionRef({ kind, name, operand, options }) {
let res;

@@ -63,3 +64,3 @@ if ((0, pattern_1.isLiteral)(operand)) {

}
res += `:${name}`;
res += (0, function_ref_1.functionRefSourceName)(kind, name);
if (options)

@@ -73,19 +74,8 @@ for (const opt of options)

}
function stringifyLiteral(lit) {
if (lit.type === 'nmtoken' && (0, names_1.isValidNmtoken)(lit.value)) {
return lit.value;
}
const esc = lit.value.replace(/\\/g, '\\\\').replace(/\|/g, '\\|');
function stringifyLiteral({ quoted, value }) {
if (!quoted && (0, names_1.isValidUnquotedLiteral)(value))
return value;
const esc = value.replace(/\\/g, '\\\\').replace(/\|/g, '\\|');
return `|${esc}|`;
}
function stringifyMarkupEnd(end) {
return `-${end.name}`;
}
function stringifyMarkupStart({ name, options }) {
let res = `+${name}`;
if (options)
for (const opt of options)
res += ' ' + stringifyOption(opt);
return res;
}
function stringifyOption(opt) {

@@ -100,12 +90,12 @@ const valueStr = (0, pattern_1.isVariableRef)(opt.value)

for (const el of body) {
res += (0, pattern_1.isText)(el) ? el.value : stringifyPlaceholder(el);
res += (0, pattern_1.isText)(el) ? el.value : stringifyExpression(el);
}
return `{${res}}`;
}
function stringifyPlaceholder(ph) {
const body = (0, pattern_1.isPlaceholder)(ph) ? ph.body : ph;
function stringifyExpression(ph) {
const body = (0, pattern_1.isExpression)(ph) ? ph.body : ph;
let res;
switch (body.type) {
case 'expression':
res = stringifyExpression(body);
case 'function':
res = stringifyFunctionRef(body);
break;

@@ -118,8 +108,2 @@ case 'junk':

break;
case 'markup-end':
res = stringifyMarkupEnd(body);
break;
case 'markup-start':
res = stringifyMarkupStart(body);
break;
case 'variable':

@@ -129,3 +113,3 @@ res = stringifyVariableRef(body);

default:
res = ''; // bad placeholder
res = ''; // bad expression
}

@@ -132,0 +116,0 @@ return `{${res}}`;

{
"name": "messageformat",
"version": "4.0.0-3.cf",
"version": "4.0.0-4",
"description": "Intl.MessageFormat / Unicode MessageFormat 2 parser, runtime and polyfill",

@@ -5,0 +5,0 @@ "keywords": [

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc