From c4fa6ad588abc77426814c67463975061b1a716f Mon Sep 17 00:00:00 2001 From: Ertanic Date: Sat, 16 Nov 2024 19:27:43 +0300 Subject: [PATCH 01/11] feat(fluent-bundle,fluent-syntax): Add source location spans to AST nodes --- fluent-bundle/src/resolver/errors.rs | 2 +- fluent-bundle/src/resolver/expression.rs | 12 +- .../src/resolver/inline_expression.rs | 25 +- fluent-bundle/src/resolver/pattern.rs | 23 +- fluent-bundle/src/resolver/scope.rs | 5 +- fluent-syntax/Cargo.toml | 1 + fluent-syntax/src/ast/helper.rs | 65 ++- fluent-syntax/src/ast/mod.rs | 381 ++++++++++++++++-- fluent-syntax/src/parser/comment.rs | 12 +- fluent-syntax/src/parser/core.rs | 64 ++- fluent-syntax/src/parser/expression.rs | 71 +++- fluent-syntax/src/parser/pattern.rs | 38 +- fluent-syntax/src/parser/runtime.rs | 21 +- fluent-syntax/src/serializer.rs | 102 +++-- fluent-syntax/tests/serializer_fixtures.rs | 2 + 15 files changed, 711 insertions(+), 113 deletions(-) diff --git a/fluent-bundle/src/resolver/errors.rs b/fluent-bundle/src/resolver/errors.rs index 7606faba..9b9f8e36 100644 --- a/fluent-bundle/src/resolver/errors.rs +++ b/fluent-bundle/src/resolver/errors.rs @@ -31,7 +31,7 @@ where InlineExpression::FunctionReference { id, .. } => Self::Function { id: id.name.to_string(), }, - InlineExpression::MessageReference { id, attribute } => Self::Message { + InlineExpression::MessageReference { id, attribute, .. } => Self::Message { id: id.name.to_string(), attribute: attribute.as_ref().map(|i| i.name.to_string()), }, diff --git a/fluent-bundle/src/resolver/expression.rs b/fluent-bundle/src/resolver/expression.rs index ce030e4c..a22505e6 100644 --- a/fluent-bundle/src/resolver/expression.rs +++ b/fluent-bundle/src/resolver/expression.rs @@ -23,15 +23,17 @@ impl<'bundle> WriteValue<'bundle> for ast::Expression<&'bundle str> { M: MemoizerKind, { match self { - Self::Inline(exp) => exp.write(w, scope), - Self::Select { selector, variants } => { + Self::Inline(exp, ..) => exp.write(w, scope), + Self::Select { + selector, variants, .. + } => { let selector = selector.resolve(scope); match selector { FluentValue::String(_) | FluentValue::Number(_) => { for variant in variants { let key = match variant.key { - ast::VariantKey::Identifier { name } => name.into(), - ast::VariantKey::NumberLiteral { value } => { + ast::VariantKey::Identifier { name, .. } => name.into(), + ast::VariantKey::NumberLiteral { value, .. } => { FluentValue::try_number(value) } }; @@ -59,7 +61,7 @@ impl<'bundle> WriteValue<'bundle> for ast::Expression<&'bundle str> { W: fmt::Write, { match self { - Self::Inline(exp) => exp.write_error(w), + Self::Inline(exp, ..) => exp.write_error(w), Self::Select { selector, .. } => selector.write_error(w), } } diff --git a/fluent-bundle/src/resolver/inline_expression.rs b/fluent-bundle/src/resolver/inline_expression.rs index 3f8c8d4f..cff88bd5 100644 --- a/fluent-bundle/src/resolver/inline_expression.rs +++ b/fluent-bundle/src/resolver/inline_expression.rs @@ -24,8 +24,8 @@ impl<'bundle> WriteValue<'bundle> for ast::InlineExpression<&'bundle str> { M: MemoizerKind, { match self { - Self::StringLiteral { value } => unescape_unicode(w, value), - Self::MessageReference { id, attribute } => { + Self::StringLiteral { value, .. } => unescape_unicode(w, value), + Self::MessageReference { id, attribute, .. } => { if let Some(msg) = scope.bundle.get_entry_message(id.name) { if let Some(attr) = attribute { msg.attributes @@ -53,11 +53,12 @@ impl<'bundle> WriteValue<'bundle> for ast::InlineExpression<&'bundle str> { scope.write_ref_error(w, self) } } - Self::NumberLiteral { value } => FluentValue::try_number(value).write(w, scope), + Self::NumberLiteral { value, .. } => FluentValue::try_number(value).write(w, scope), Self::TermReference { id, attribute, arguments, + .. } => { let (_, resolved_named_args) = scope.get_arguments(arguments.as_ref()); @@ -82,7 +83,7 @@ impl<'bundle> WriteValue<'bundle> for ast::InlineExpression<&'bundle str> { scope.local_args = None; result } - Self::FunctionReference { id, arguments } => { + Self::FunctionReference { id, arguments, .. } => { let (resolved_positional_args, resolved_named_args) = scope.get_arguments(Some(arguments)); @@ -99,7 +100,7 @@ impl<'bundle> WriteValue<'bundle> for ast::InlineExpression<&'bundle str> { scope.write_ref_error(w, self) } } - Self::VariableReference { id } => { + Self::VariableReference { id, .. } => { let args = scope.local_args.as_ref().or(scope.args); if let Some(arg) = args.and_then(|args| args.get(id.name)) { @@ -113,7 +114,7 @@ impl<'bundle> WriteValue<'bundle> for ast::InlineExpression<&'bundle str> { w.write_char('}') } } - Self::Placeable { expression } => expression.write(w, scope), + Self::Placeable { expression, .. } => expression.write(w, scope), } } @@ -125,10 +126,12 @@ impl<'bundle> WriteValue<'bundle> for ast::InlineExpression<&'bundle str> { Self::MessageReference { id, attribute: Some(attribute), + .. } => write!(w, "{}.{}", id.name, attribute.name), Self::MessageReference { id, attribute: None, + .. } => w.write_str(id.name), Self::TermReference { id, @@ -141,7 +144,7 @@ impl<'bundle> WriteValue<'bundle> for ast::InlineExpression<&'bundle str> { .. } => write!(w, "-{}", id.name), Self::FunctionReference { id, .. } => write!(w, "{}()", id.name), - Self::VariableReference { id } => write!(w, "${}", id.name), + Self::VariableReference { id, .. } => write!(w, "${}", id.name), _ => unreachable!(), } } @@ -157,9 +160,9 @@ impl<'bundle> ResolveValue<'bundle> for ast::InlineExpression<&'bundle str> { M: MemoizerKind, { match self { - Self::StringLiteral { value } => unescape_unicode_to_string(value).into(), - Self::NumberLiteral { value } => FluentValue::try_number(value), - Self::VariableReference { id } => { + Self::StringLiteral { value, .. } => unescape_unicode_to_string(value).into(), + Self::NumberLiteral { value, .. } => FluentValue::try_number(value), + Self::VariableReference { id, .. } => { if let Some(local_args) = &scope.local_args { if let Some(arg) = local_args.get(id.name) { return arg.clone(); @@ -173,7 +176,7 @@ impl<'bundle> ResolveValue<'bundle> for ast::InlineExpression<&'bundle str> { } FluentValue::Error } - Self::FunctionReference { id, arguments } => { + Self::FunctionReference { id, arguments, .. } => { let (resolved_positional_args, resolved_named_args) = scope.get_arguments(Some(arguments)); diff --git a/fluent-bundle/src/resolver/pattern.rs b/fluent-bundle/src/resolver/pattern.rs index e20bfcde..d09547aa 100644 --- a/fluent-bundle/src/resolver/pattern.rs +++ b/fluent-bundle/src/resolver/pattern.rs @@ -32,14 +32,14 @@ impl<'bundle> WriteValue<'bundle> for ast::Pattern<&'bundle str> { } match elem { - ast::PatternElement::TextElement { value } => { + ast::PatternElement::TextElement { value, .. } => { if let Some(ref transform) = scope.bundle.transform { w.write_str(&transform(value))?; } else { w.write_str(value)?; } } - ast::PatternElement::Placeable { ref expression } => { + ast::PatternElement::Placeable { ref expression, .. } => { scope.placeables += 1; if scope.placeables > MAX_PLACEABLES { scope.dirty = true; @@ -51,13 +51,16 @@ impl<'bundle> WriteValue<'bundle> for ast::Pattern<&'bundle str> { && len > 1 && !matches!( expression, - ast::Expression::Inline(ast::InlineExpression::MessageReference { .. },) - | ast::Expression::Inline( - ast::InlineExpression::TermReference { .. }, - ) - | ast::Expression::Inline( - ast::InlineExpression::StringLiteral { .. }, - ) + ast::Expression::Inline( + ast::InlineExpression::MessageReference { .. }, + .. + ) | ast::Expression::Inline( + ast::InlineExpression::TermReference { .. }, + .. + ) | ast::Expression::Inline( + ast::InlineExpression::StringLiteral { .. }, + .. + ) ); if needs_isolation { w.write_char('\u{2068}')?; @@ -92,7 +95,7 @@ impl<'bundle> ResolveValue<'bundle> for ast::Pattern<&'bundle str> { let len = self.elements.len(); if len == 1 { - if let ast::PatternElement::TextElement { value } = self.elements[0] { + if let ast::PatternElement::TextElement { value, .. } = self.elements[0] { return scope .bundle .transform diff --git a/fluent-bundle/src/resolver/scope.rs b/fluent-bundle/src/resolver/scope.rs index 1ddff1a4..1355c0e9 100644 --- a/fluent-bundle/src/resolver/scope.rs +++ b/fluent-bundle/src/resolver/scope.rs @@ -124,7 +124,10 @@ impl<'bundle, 'ast, 'args, 'errors, R, M> Scope<'bundle, 'ast, 'args, 'errors, R R: Borrow, M: MemoizerKind, { - if let Some(ast::CallArguments { positional, named }) = arguments { + if let Some(ast::CallArguments { + positional, named, .. + }) = arguments + { let positional = positional.iter().map(|expr| expr.resolve(self)).collect(); let named = named diff --git a/fluent-syntax/Cargo.toml b/fluent-syntax/Cargo.toml index b8cf539a..e9efcd54 100644 --- a/fluent-syntax/Cargo.toml +++ b/fluent-syntax/Cargo.toml @@ -38,6 +38,7 @@ glob = "0.3" [features] default = [] +spans = [] serde = ["dep:serde"] json = ["serde", "dep:serde_json"] all-benchmarks = [] diff --git a/fluent-syntax/src/ast/helper.rs b/fluent-syntax/src/ast/helper.rs index 23851301..71b5750a 100644 --- a/fluent-syntax/src/ast/helper.rs +++ b/fluent-syntax/src/ast/helper.rs @@ -1,25 +1,78 @@ +use super::Comment; +#[cfg(feature = "spans")] +use super::Span; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use super::Comment; // This is a helper struct used to properly deserialize referential // JSON comments which are single continuous String, into a vec of // content slices. -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Clone)] +#[cfg_attr(not(feature = "spans"), derive(PartialEq, Eq))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(untagged))] pub enum CommentDef { - Single { content: S }, - Multi { content: Vec }, + Single { + content: S, + #[cfg(feature = "spans")] + span: Span, + }, + Multi { + content: Vec, + #[cfg(feature = "spans")] + span: Span, + }, +} + +#[cfg(feature = "spans")] +impl Eq for CommentDef {} + +#[cfg(feature = "spans")] +impl PartialEq for CommentDef { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + ( + Self::Single { + content: l_content, .. + }, + Self::Single { + content: r_content, .. + }, + ) => l_content == r_content, + ( + Self::Multi { + content: l_content, .. + }, + Self::Multi { + content: r_content, .. + }, + ) => l_content == r_content, + _ => false, + } + } } impl From> for Comment { fn from(input: CommentDef) -> Self { match input { - CommentDef::Single { content } => Self { + CommentDef::Single { + content, + #[cfg(feature = "spans")] + span, + } => Self { content: vec![content], + #[cfg(feature = "spans")] + span, + }, + CommentDef::Multi { + content, + #[cfg(feature = "spans")] + span, + } => Self { + content, + #[cfg(feature = "spans")] + span, }, - CommentDef::Multi { content } => Self { content }, } } } diff --git a/fluent-syntax/src/ast/mod.rs b/fluent-syntax/src/ast/mod.rs index 273aceaf..ec563484 100644 --- a/fluent-syntax/src/ast/mod.rs +++ b/fluent-syntax/src/ast/mod.rs @@ -88,6 +88,8 @@ mod helper; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "spans")] +use std::ops::Range; /// Root node of a Fluent Translation List. /// @@ -111,10 +113,20 @@ use serde::{Deserialize, Serialize}; /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] +#[cfg_attr(not(feature = "spans"), derive(PartialEq))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Resource { pub body: Vec>, + #[cfg(feature = "spans")] + pub span: Span, +} + +#[cfg(feature = "spans")] +impl PartialEq for Resource { + fn eq(&self, other: &Self) -> bool { + self.body == other.body + } } /// A top-level node representing an entry of a [`Resource`]. @@ -193,7 +205,8 @@ pub struct Resource { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] +#[cfg_attr(not(feature = "spans"), derive(PartialEq))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub enum Entry { @@ -202,7 +215,33 @@ pub enum Entry { Comment(Comment), GroupComment(Comment), ResourceComment(Comment), - Junk { content: S }, + Junk { + content: S, + #[cfg(feature = "spans")] + span: Span, + }, +} + +#[cfg(feature = "spans")] +impl PartialEq for Entry { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Message(l0), Self::Message(r0)) => l0 == r0, + (Self::Term(l0), Self::Term(r0)) => l0 == r0, + (Self::Comment(l0), Self::Comment(r0)) => l0 == r0, + (Self::GroupComment(l0), Self::GroupComment(r0)) => l0 == r0, + (Self::ResourceComment(l0), Self::ResourceComment(r0)) => l0 == r0, + ( + Self::Junk { + content: l_content, .. + }, + Self::Junk { + content: r_content, .. + }, + ) => l_content == r_content, + _ => false, + } + } } /// Message node represents the most common [`Entry`] in an FTL [`Resource`]. @@ -253,13 +292,24 @@ pub enum Entry { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Message { pub id: Identifier, pub value: Option>, pub attributes: Vec>, pub comment: Option>, + #[cfg(feature = "spans")] + pub span: Span, +} + +impl PartialEq for Message { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + && self.value == other.value + && self.attributes == other.attributes + && self.comment == other.comment + } } /// A Fluent [`Term`]. @@ -307,13 +357,26 @@ pub struct Message { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] +#[cfg_attr(not(feature = "spans"), derive(PartialEq))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Term { pub id: Identifier, pub value: Pattern, pub attributes: Vec>, pub comment: Option>, + #[cfg(feature = "spans")] + pub span: Span, +} + +#[cfg(feature = "spans")] +impl PartialEq for Term { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + && self.value == other.value + && self.attributes == other.attributes + && self.comment == other.comment + } } /// Pattern contains a value of a [`Message`], [`Term`] or an [`Attribute`]. @@ -387,10 +450,18 @@ pub struct Term { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Pattern { pub elements: Vec>, + #[cfg(feature = "spans")] + pub span: Span, +} + +impl PartialEq for Pattern { + fn eq(&self, other: &Self) -> bool { + self.elements == other.elements + } } /// `PatternElement` is an element of a [`Pattern`]. @@ -464,12 +535,42 @@ pub struct Pattern { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub enum PatternElement { - TextElement { value: S }, - Placeable { expression: Expression }, + TextElement { + value: S, + #[cfg(feature = "spans")] + span: Span, + }, + Placeable { + expression: Expression, + #[cfg(feature = "spans")] + span: Span, + }, +} + +impl PartialEq for PatternElement { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + ( + Self::TextElement { value: l_value, .. }, + Self::TextElement { value: r_value, .. }, + ) => l_value == r_value, + ( + Self::Placeable { + expression: l_expression, + .. + }, + Self::Placeable { + expression: r_expression, + .. + }, + ) => l_expression == r_expression, + _ => false, + } + } } /// Attribute represents a part of a [`Message`] or [`Term`]. @@ -535,11 +636,21 @@ pub enum PatternElement { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] +#[cfg_attr(not(feature = "spans"), derive(PartialEq))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Attribute { pub id: Identifier, pub value: Pattern, + #[cfg(feature = "spans")] + pub span: Span, +} + +#[cfg(feature = "spans")] +impl PartialEq for Attribute { + fn eq(&self, other: &Self) -> bool { + self.id == other.id && self.value == other.value + } } /// Identifier is part of nodes such as [`Message`], [`Term`] and [`Attribute`]. @@ -584,10 +695,20 @@ pub struct Attribute { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Identifier { pub name: S, + #[cfg(feature = "spans")] + pub span: Span, +} + +impl Eq for Identifier {} + +impl PartialEq for Identifier { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + } } /// Variant is a single branch of a value in a [`Select`](Expression::Select) expression. @@ -667,13 +788,23 @@ pub struct Identifier { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] +#[cfg_attr(not(feature = "spans"), derive(PartialEq))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub struct Variant { pub key: VariantKey, pub value: Pattern, pub default: bool, + #[cfg(feature = "spans")] + pub span: Span, +} + +#[cfg(feature = "spans")] +impl PartialEq for Variant { + fn eq(&self, other: &Self) -> bool { + self.key == other.key && self.value == other.value && self.default == other.default + } } /// A key of a [`Variant`]. @@ -756,8 +887,16 @@ pub struct Variant { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub enum VariantKey { - Identifier { name: S }, - NumberLiteral { value: S }, + Identifier { + name: S, + #[cfg(feature = "spans")] + span: Span, + }, + NumberLiteral { + value: S, + #[cfg(feature = "spans")] + span: Span, + }, } /// Fluent [`Comment`]. @@ -798,11 +937,21 @@ pub enum VariantKey { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(from = "helper::CommentDef"))] pub struct Comment { pub content: Vec, + #[cfg(feature = "spans")] + pub span: Span, +} + +impl Eq for Comment {} + +impl PartialEq for Comment { + fn eq(&self, other: &Self) -> bool { + self.content == other.content + } } /// List of arguments for a [`FunctionReference`](InlineExpression::FunctionReference) or a @@ -879,12 +1028,20 @@ pub struct Comment { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone, Default)] +#[derive(Debug, Clone, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub struct CallArguments { pub positional: Vec>, pub named: Vec>, + #[cfg(feature = "spans")] + pub span: Span, +} + +impl PartialEq for CallArguments { + fn eq(&self, other: &Self) -> bool { + self.positional == other.positional && self.named == other.named + } } /// A key-value pair used in [`CallArguments`]. @@ -948,12 +1105,22 @@ pub struct CallArguments { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] +#[cfg_attr(not(feature = "spans"), derive(PartialEq))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub struct NamedArgument { pub name: Identifier, pub value: InlineExpression, + #[cfg(feature = "spans")] + pub span: Span, +} + +#[cfg(feature = "spans")] +impl PartialEq for NamedArgument { + fn eq(&self, other: &Self) -> bool { + self.name == other.name && self.value == other.value + } } /// A subset of expressions which can be used as [`Placeable`](PatternElement::Placeable), @@ -1004,7 +1171,7 @@ pub struct NamedArgument { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub enum InlineExpression { @@ -1053,7 +1220,11 @@ pub enum InlineExpression { /// } /// ); /// ``` - StringLiteral { value: S }, + StringLiteral { + value: S, + #[cfg(feature = "spans")] + span: Span, + }, /// A number literal. /// /// # Example @@ -1099,7 +1270,11 @@ pub enum InlineExpression { /// } /// ); /// ``` - NumberLiteral { value: S }, + NumberLiteral { + value: S, + #[cfg(feature = "spans")] + span: Span, + }, /// A function reference. /// /// # Example @@ -1151,6 +1326,8 @@ pub enum InlineExpression { FunctionReference { id: Identifier, arguments: CallArguments, + #[cfg(feature = "spans")] + span: Span, }, /// A reference to another message. /// @@ -1203,6 +1380,8 @@ pub enum InlineExpression { MessageReference { id: Identifier, attribute: Option>, + #[cfg(feature = "spans")] + span: Span, }, /// A reference to a term. /// @@ -1257,6 +1436,8 @@ pub enum InlineExpression { id: Identifier, attribute: Option>, arguments: Option>, + #[cfg(feature = "spans")] + span: Span, }, /// A reference to a variable. /// @@ -1305,7 +1486,11 @@ pub enum InlineExpression { /// } /// ); /// ``` - VariableReference { id: Identifier }, + VariableReference { + id: Identifier, + #[cfg(feature = "spans")] + span: Span, + }, /// A placeable which may contain another expression. /// /// # Example @@ -1357,7 +1542,94 @@ pub enum InlineExpression { /// } /// ); /// ``` - Placeable { expression: Box> }, + Placeable { + expression: Box>, + #[cfg(feature = "spans")] + span: Span, + }, +} + +impl PartialEq for InlineExpression { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + ( + Self::StringLiteral { value: l_value, .. }, + Self::StringLiteral { value: r_value, .. }, + ) => l_value == r_value, + ( + Self::NumberLiteral { value: l_value, .. }, + Self::NumberLiteral { value: r_value, .. }, + ) => l_value == r_value, + ( + Self::FunctionReference { + id: l_id, + arguments: l_arguments, + .. + }, + Self::FunctionReference { + id: r_id, + arguments: r_arguments, + .. + }, + ) => l_id == r_id && l_arguments == r_arguments, + ( + Self::MessageReference { + id: l_id, + attribute: l_attribute, + .. + }, + Self::MessageReference { + id: r_id, + attribute: r_attribute, + .. + }, + ) => l_id == r_id && l_attribute == r_attribute, + ( + Self::TermReference { + id: l_id, + attribute: l_attribute, + arguments: l_arguments, + .. + }, + Self::TermReference { + id: r_id, + attribute: r_attribute, + arguments: r_arguments, + .. + }, + ) => l_id == r_id && l_attribute == r_attribute && l_arguments == r_arguments, + ( + Self::VariableReference { id: l_id, .. }, + Self::VariableReference { id: r_id, .. }, + ) => l_id == r_id, + ( + Self::Placeable { + expression: l_expression, + .. + }, + Self::Placeable { + expression: r_expression, + .. + }, + ) => l_expression == r_expression, + _ => false, + } + } +} + +#[cfg(feature = "spans")] +impl InlineExpression { + pub fn get_span(&self) -> Span { + match self { + InlineExpression::StringLiteral { span, .. } + | InlineExpression::TermReference { span, .. } + | InlineExpression::VariableReference { span, .. } + | InlineExpression::Placeable { span, .. } + | InlineExpression::NumberLiteral { span, .. } + | InlineExpression::FunctionReference { span, .. } + | InlineExpression::MessageReference { span, .. } => *span, + } + } } /// An expression that is either a select expression or an inline expression. @@ -1434,7 +1706,8 @@ pub enum InlineExpression { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] +#[cfg_attr(not(feature = "spans"), derive(PartialEq))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(untagged))] pub enum Expression { @@ -1448,6 +1721,8 @@ pub enum Expression { Select { selector: InlineExpression, variants: Vec>, + #[cfg(feature = "spans")] + span: Span, }, /// An inline expression such as `${ username }`: @@ -1455,5 +1730,63 @@ pub enum Expression { /// ```ftl /// hello-user = Hello ${ username } /// ``` - Inline(InlineExpression), + Inline(InlineExpression, #[cfg(feature = "spans")] Span), +} + +#[cfg(feature = "spans")] +impl PartialEq for Expression { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + ( + Self::Select { + selector: l_selector, + variants: l_variants, + .. + }, + Self::Select { + selector: r_selector, + variants: r_variants, + .. + }, + ) => l_selector == r_selector && l_variants == r_variants, + (Self::Inline(l0, ..), Self::Inline(r0, ..)) => l0 == r0, + _ => false, + } + } +} + +/// A span of a node. Allows you to get the index of the start and end character of a node. +/// +/// # Example +/// +/// ``` +/// #![cfg(feature = "spans")] +/// +/// use fluent_syntax::parser; +/// use fluent_syntax::ast::*; +/// +/// let ftl = "hello-world = Hello, World!"; +/// +/// let resource = parser::parse(ftl).expect("Failed to parse an FTL resource."); +/// let Entry::Message(Message { ref id, .. }) = resource.body[0] else { unreachable!() }; +/// +/// assert_eq!(resource.span, Span { start: 0, end: 27 }); +/// assert_eq!(id.span, Span { start: 0, end: 11 }); // the span of hello-world identifier +/// ``` +#[cfg(feature = "spans")] +#[derive(Debug, Clone, Copy, Default, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Span { + pub start: usize, + pub end: usize, +} + +#[cfg(feature = "spans")] +impl Span { + pub fn new(range: Range) -> Self { + Self { + start: range.start, + end: range.end, + } + } } diff --git a/fluent-syntax/src/parser/comment.rs b/fluent-syntax/src/parser/comment.rs index 1e30fc72..9fad6d2c 100644 --- a/fluent-syntax/src/parser/comment.rs +++ b/fluent-syntax/src/parser/comment.rs @@ -17,6 +17,9 @@ where let mut level = Level::None; let mut content = vec![]; + #[cfg(feature = "spans")] + let start_pos = self.ptr; + while self.ptr < self.length { let line_level = self.get_comment_level(); if line_level == Level::None { @@ -47,7 +50,14 @@ where self.skip_eol(); } - Ok((ast::Comment { content }, level)) + Ok(( + ast::Comment { + content, + #[cfg(feature = "spans")] + span: ast::Span::new(start_pos..self.ptr), + }, + level, + )) } pub(super) fn skip_comment(&mut self) { diff --git a/fluent-syntax/src/parser/core.rs b/fluent-syntax/src/parser/core.rs index 68ad8dc0..d9059a8b 100644 --- a/fluent-syntax/src/parser/core.rs +++ b/fluent-syntax/src/parser/core.rs @@ -3,7 +3,7 @@ use super::{ errors::{ErrorKind, ParserError}, slice::Slice, }; -use crate::ast; +use crate::ast::{self, Span}; pub type Result = std::result::Result; @@ -67,7 +67,11 @@ where err.slice = Some(entry_start..self.ptr); errors.push(err); let content = self.source.slice(entry_start..self.ptr); - body.push(ast::Entry::Junk { content }); + body.push(ast::Entry::Junk { + content, + #[cfg(feature = "spans")] + span: ast::Span::new(entry_start..self.ptr), + }); } } last_blank_count = self.skip_blank_block(); @@ -77,9 +81,20 @@ where body.push(ast::Entry::Comment(last_comment)); } if errors.is_empty() { - Ok(ast::Resource { body }) + Ok(ast::Resource { + body, + #[cfg(feature = "spans")] + span: ast::Span::new(0..self.length), + }) } else { - Err((ast::Resource { body }, errors)) + Err(( + ast::Resource { + body, + #[cfg(feature = "spans")] + span: ast::Span::new(0..self.length), + }, + errors, + )) } } @@ -123,6 +138,8 @@ where value: pattern, attributes, comment: None, + #[cfg(feature = "spans")] + span: ast::Span::new(entry_start..self.ptr), }) } @@ -145,6 +162,8 @@ where value, attributes, comment: None, + #[cfg(feature = "spans")] + span: ast::Span::new(entry_start..self.ptr), }) } else { error!( @@ -184,12 +203,19 @@ where let pattern = self.get_pattern()?; match pattern { - Some(pattern) => Ok(ast::Attribute { id, value: pattern }), + Some(pattern) => Ok(ast::Attribute { + id, + value: pattern, + #[cfg(feature = "spans")] + span: ast::Span::new(self.ptr - 1..self.ptr), + }), None => error!(ErrorKind::MissingValue, self.ptr), } } pub(super) fn get_identifier_unchecked(&mut self) -> ast::Identifier { + #[cfg(feature = "spans")] + let start = self.ptr - 1; let mut ptr = self.ptr; while matches!(get_byte!(self, ptr), Some(b) if b.is_ascii_alphanumeric() || *b == b'-' || *b == b'_') @@ -200,7 +226,11 @@ where let name = self.source.slice(self.ptr - 1..ptr); self.ptr = ptr; - ast::Identifier { name } + ast::Identifier { + name, + #[cfg(feature = "spans")] + span: ast::Span::new(start..self.ptr), + } } pub(super) fn get_identifier(&mut self) -> Result> { @@ -229,12 +259,22 @@ where self.skip_blank(); let key = if self.is_number_start() { + #[cfg(feature = "spans")] + let start = self.ptr; + ast::VariantKey::NumberLiteral { value: self.get_number_literal()?, + #[cfg(feature = "spans")] + span: Span(start..self.ptr), } } else { + #[cfg(feature = "spans")] + let start = self.ptr; + ast::VariantKey::Identifier { name: self.get_identifier()?.name, + #[cfg(feature = "spans")] + span: Span(start..self.ptr), } }; @@ -259,6 +299,9 @@ where } } + #[cfg(feature = "spans")] + let start = self.ptr; + if !self.take_byte_if(b'[') { break; } @@ -272,6 +315,8 @@ where key, value, default, + #[cfg(feature = "spans")] + span: ast::Span::new((if default { start - 1 } else { start })..self.ptr), }); self.skip_blank(); } else { @@ -293,9 +338,10 @@ where self.expect_byte(b'}')?; let invalid_expression_found = match &exp { - ast::Expression::Inline(ast::InlineExpression::TermReference { - ref attribute, .. - }) => attribute.is_some(), + ast::Expression::Inline( + ast::InlineExpression::TermReference { ref attribute, .. }, + .., + ) => attribute.is_some(), _ => false, }; if invalid_expression_found { diff --git a/fluent-syntax/src/parser/expression.rs b/fluent-syntax/src/parser/expression.rs index c5ccb32b..014228e0 100644 --- a/fluent-syntax/src/parser/expression.rs +++ b/fluent-syntax/src/parser/expression.rs @@ -9,6 +9,9 @@ where pub(super) fn get_expression(&mut self) -> Result> { let exp = self.get_inline_expression(false)?; + #[cfg(feature = "spans")] + let start_span = exp.get_span().start; + self.skip_blank(); if !self.is_current_byte(b'-') || !self.is_byte_at(b'>', self.ptr + 1) { @@ -17,7 +20,11 @@ where return error!(ErrorKind::TermAttributeAsPlaceable, self.ptr); } } - return Ok(ast::Expression::Inline(exp)); + return Ok(ast::Expression::Inline( + exp, + #[cfg(feature = "spans")] + ast::Span::new(start_span..self.ptr), + )); } match exp { @@ -60,6 +67,8 @@ where Ok(ast::Expression::Select { selector: exp, variants, + #[cfg(feature = "spans")] + span: ast::Span::new(start_span..self.ptr), }) } @@ -67,10 +76,10 @@ where &mut self, only_literal: bool, ) -> Result> { + let start = self.ptr; match get_current_byte!(self) { Some(b'"') => { self.ptr += 1; // " - let start = self.ptr; while let Some(b) = get_current_byte!(self) { match b { b'\\' => match get_byte!(self, self.ptr + 1) { @@ -99,12 +108,20 @@ where } self.expect_byte(b'"')?; - let slice = self.source.slice(start..self.ptr - 1); - Ok(ast::InlineExpression::StringLiteral { value: slice }) + let slice = self.source.slice(start + 1..self.ptr - 1); + Ok(ast::InlineExpression::StringLiteral { + value: slice, + #[cfg(feature = "spans")] + span: ast::Span::new(start..self.ptr), + }) } Some(b) if b.is_ascii_digit() => { let num = self.get_number_literal()?; - Ok(ast::InlineExpression::NumberLiteral { value: num }) + Ok(ast::InlineExpression::NumberLiteral { + value: num, + #[cfg(feature = "spans")] + span: ast::Span::new(start..self.ptr), + }) } Some(b'-') if !only_literal => { self.ptr += 1; // - @@ -117,17 +134,27 @@ where id, attribute, arguments, + #[cfg(feature = "spans")] + span: ast::Span::new(start..self.ptr), }) } else { self.ptr -= 1; let num = self.get_number_literal()?; - Ok(ast::InlineExpression::NumberLiteral { value: num }) + Ok(ast::InlineExpression::NumberLiteral { + value: num, + #[cfg(feature = "spans")] + span: ast::Span::new(start..self.ptr), + }) } } Some(b'$') if !only_literal => { self.ptr += 1; // $ let id = self.get_identifier()?; - Ok(ast::InlineExpression::VariableReference { id }) + Ok(ast::InlineExpression::VariableReference { + id, + #[cfg(feature = "spans")] + span: ast::Span::new(start..self.ptr), + }) } Some(b) if b.is_ascii_alphabetic() => { self.ptr += 1; @@ -138,10 +165,20 @@ where return error!(ErrorKind::ForbiddenCallee, self.ptr); } - Ok(ast::InlineExpression::FunctionReference { id, arguments }) + Ok(ast::InlineExpression::FunctionReference { + id, + arguments, + #[cfg(feature = "spans")] + span: ast::Span::new(start..self.ptr), + }) } else { let attribute = self.get_attribute_accessor()?; - Ok(ast::InlineExpression::MessageReference { id, attribute }) + Ok(ast::InlineExpression::MessageReference { + id, + attribute, + #[cfg(feature = "spans")] + span: ast::Span::new(start..self.ptr), + }) } } Some(b'{') if !only_literal => { @@ -149,6 +186,8 @@ where let exp = self.get_placeable()?; Ok(ast::InlineExpression::Placeable { expression: Box::new(exp), + #[cfg(feature = "spans")] + span: ast::Span::new(start..self.ptr), }) } _ if only_literal => error!(ErrorKind::ExpectedLiteral, self.ptr), @@ -161,6 +200,8 @@ where if !self.take_byte_if(b'(') { return Ok(None); } + #[cfg(feature = "spans")] + let start = self.ptr - 1; let mut positional = vec![]; let mut named = vec![]; @@ -178,6 +219,7 @@ where if let ast::InlineExpression::MessageReference { ref id, attribute: None, + .. } = expr { self.skip_blank(); @@ -196,8 +238,12 @@ where named.push(ast::NamedArgument { name: ast::Identifier { name: id.name.clone(), + #[cfg(feature = "spans")] + span: id.span, }, value: val, + #[cfg(feature = "spans")] + span: ast::Span::new(id.span.start..self.ptr), }); } else { if !argument_names.is_empty() { @@ -219,6 +265,11 @@ where self.expect_byte(b')')?; - Ok(Some(ast::CallArguments { positional, named })) + Ok(Some(ast::CallArguments { + positional, + named, + #[cfg(feature = "spans")] + span: ast::Span::new(start..self.ptr), + })) } } diff --git a/fluent-syntax/src/parser/pattern.rs b/fluent-syntax/src/parser/pattern.rs index 9ca1229a..d0a6330d 100644 --- a/fluent-syntax/src/parser/pattern.rs +++ b/fluent-syntax/src/parser/pattern.rs @@ -1,6 +1,8 @@ use super::errors::{ErrorKind, ParserError}; use super::{core::Parser, core::Result, slice::Slice}; use crate::ast; +#[cfg(feature = "spans")] +use std::ops::Range; #[derive(Debug, PartialEq)] enum TextElementTermination { @@ -24,7 +26,7 @@ enum TextElementPosition { // cheaper since they'll happen on the pointers, rather than extracted slices. #[derive(Debug)] enum PatternElementPlaceholders { - Placeable(ast::Expression), + Placeable(ast::Expression, #[cfg(feature = "spans")] Range), // (start, end, indent, position) TextElement(usize, usize, usize, TextElementPosition), } @@ -49,6 +51,9 @@ where self.skip_blank_inline(); + #[cfg(feature = "spans")] + let start_pos = self.ptr; + let mut text_element_role = if self.skip_eol() { self.skip_blank_block(); TextElementPosition::LineStart @@ -58,12 +63,23 @@ where while self.ptr < self.length { if self.take_byte_if(b'{') { + #[cfg(feature = "spans")] + let slice_start = self.ptr - 1; if text_element_role == TextElementPosition::LineStart { common_indent = Some(0); } let exp = self.get_placeable()?; last_non_blank = Some(elements.len()); + + #[cfg(feature = "spans")] + elements.push(PatternElementPlaceholders::Placeable( + exp, + slice_start..self.ptr - 1, + )); + + #[cfg(not(feature = "spans"))] elements.push(PatternElementPlaceholders::Placeable(exp)); + text_element_role = TextElementPosition::Continuation; } else { let slice_start = self.ptr; @@ -127,6 +143,14 @@ where .take(last_non_blank + 1) .enumerate() .map(|(i, elem)| match elem { + #[cfg(feature = "spans")] + PatternElementPlaceholders::Placeable(expression, range) => { + ast::PatternElement::Placeable { + expression, + span: ast::Span::new(range), + } + } + #[cfg(not(feature = "spans"))] PatternElementPlaceholders::Placeable(expression) => { ast::PatternElement::Placeable { expression } } @@ -143,11 +167,19 @@ where if last_non_blank == i { value.trim(); } - ast::PatternElement::TextElement { value } + ast::PatternElement::TextElement { + value, + #[cfg(feature = "spans")] + span: ast::Span::new(start..end), + } } }) .collect(); - return Ok(Some(ast::Pattern { elements })); + return Ok(Some(ast::Pattern { + elements, + #[cfg(feature = "spans")] + span: ast::Span::new(start_pos..self.ptr), + })); } Ok(None) diff --git a/fluent-syntax/src/parser/runtime.rs b/fluent-syntax/src/parser/runtime.rs index e116ceae..4c7ce18d 100644 --- a/fluent-syntax/src/parser/runtime.rs +++ b/fluent-syntax/src/parser/runtime.rs @@ -34,16 +34,31 @@ where err.slice = Some(entry_start..self.ptr); errors.push(err); let content = self.source.slice(entry_start..self.ptr); - body.push(ast::Entry::Junk { content }); + body.push(ast::Entry::Junk { + content, + #[cfg(feature = "spans")] + span: ast::Span::new(entry_start..self.ptr), + }); } } self.skip_blank_block(); } if errors.is_empty() { - Ok(ast::Resource { body }) + Ok(ast::Resource { + body, + #[cfg(feature = "spans")] + span: ast::Span::new(0..self.length), + }) } else { - Err((ast::Resource { body }, errors)) + Err(( + ast::Resource { + body, + #[cfg(feature = "spans")] + span: ast::Span::new(0..self.length), + }, + errors, + )) } } diff --git a/fluent-syntax/src/serializer.rs b/fluent-syntax/src/serializer.rs index a3442429..a6dba321 100644 --- a/fluent-syntax/src/serializer.rs +++ b/fluent-syntax/src/serializer.rs @@ -87,7 +87,7 @@ impl Serializer { Entry::Comment(comment) => self.serialize_free_comment(comment, "#"), Entry::GroupComment(comment) => self.serialize_free_comment(comment, "##"), Entry::ResourceComment(comment) => self.serialize_free_comment(comment, "###"), - Entry::Junk { content } => { + Entry::Junk { content, .. } => { if self.options.with_junk { self.serialize_junk(content.as_ref()); } @@ -203,9 +203,9 @@ impl Serializer { fn serialize_element<'s, S: Slice<'s>>(&mut self, elem: &PatternElement) { match elem { - PatternElement::TextElement { value } => self.writer.write_literal(value.as_ref()), - PatternElement::Placeable { expression } => match expression { - Expression::Inline(InlineExpression::Placeable { expression }) => { + PatternElement::TextElement { value, .. } => self.writer.write_literal(value.as_ref()), + PatternElement::Placeable { expression, .. } => match expression { + Expression::Inline(InlineExpression::Placeable { expression, .. }, ..) => { // A placeable inside a placeable is a special case because we // don't want the braces to look silly (e.g. "{ { Foo() } }"). self.writer.write_literal("{{ "); @@ -219,7 +219,7 @@ impl Serializer { self.serialize_expression(expression); self.writer.write_literal("}"); } - Expression::Inline(_) => { + Expression::Inline(..) => { self.writer.write_literal("{ "); self.serialize_expression(expression); self.writer.write_literal(" }"); @@ -230,8 +230,10 @@ impl Serializer { fn serialize_expression<'s, S: Slice<'s>>(&mut self, expr: &Expression) { match expr { - Expression::Inline(inline) => self.serialize_inline_expression(inline), - Expression::Select { selector, variants } => { + Expression::Inline(inline, ..) => self.serialize_inline_expression(inline), + Expression::Select { + selector, variants, .. + } => { self.serialize_select_expression(selector, variants); } } @@ -239,23 +241,26 @@ impl Serializer { fn serialize_inline_expression<'s, S: Slice<'s>>(&mut self, expr: &InlineExpression) { match expr { - InlineExpression::StringLiteral { value } => { + InlineExpression::StringLiteral { value, .. } => { self.writer.write_literal("\""); self.writer.write_literal(value.as_ref()); self.writer.write_literal("\""); } - InlineExpression::NumberLiteral { value } => self.writer.write_literal(value.as_ref()), + InlineExpression::NumberLiteral { value, .. } => { + self.writer.write_literal(value.as_ref()) + } InlineExpression::VariableReference { - id: Identifier { name: value }, + id: Identifier { name: value, .. }, + .. } => { self.writer.write_literal("$"); self.writer.write_literal(value.as_ref()); } - InlineExpression::FunctionReference { id, arguments } => { + InlineExpression::FunctionReference { id, arguments, .. } => { self.writer.write_literal(id.name.as_ref()); self.serialize_call_arguments(arguments); } - InlineExpression::MessageReference { id, attribute } => { + InlineExpression::MessageReference { id, attribute, .. } => { self.writer.write_literal(id.name.as_ref()); if let Some(attr) = attribute.as_ref() { @@ -267,6 +272,7 @@ impl Serializer { id, attribute, arguments, + .. } => { self.writer.write_literal("-"); self.writer.write_literal(id.name.as_ref()); @@ -279,7 +285,7 @@ impl Serializer { self.serialize_call_arguments(args); } } - InlineExpression::Placeable { expression } => { + InlineExpression::Placeable { expression, .. } => { self.writer.write_literal("{"); self.serialize_expression(expression); self.writer.write_literal("}"); @@ -319,7 +325,8 @@ impl Serializer { fn serialize_variant_key<'s, S: Slice<'s>>(&mut self, key: &VariantKey) { match key { - VariantKey::NumberLiteral { value } | VariantKey::Identifier { name: value } => { + VariantKey::NumberLiteral { value, .. } + | VariantKey::Identifier { name: value, .. } => { self.writer.write_literal(value.as_ref()); } } @@ -361,13 +368,13 @@ impl<'s, S: Slice<'s>> Pattern { fn is_multiline(&self) -> bool { self.elements.iter().any(|elem| match elem { - PatternElement::TextElement { value } => value.as_ref().contains('\n'), - PatternElement::Placeable { expression } => is_select_expr(expression), + PatternElement::TextElement { value, .. } => value.as_ref().contains('\n'), + PatternElement::Placeable { expression, .. } => is_select_expr(expression), }) } fn has_leading_text_dot(&self) -> bool { - if let Some(PatternElement::TextElement { value }) = self.elements.first() { + if let Some(PatternElement::TextElement { value, .. }) = self.elements.first() { value.as_ref().starts_with('.') } else { false @@ -378,10 +385,10 @@ impl<'s, S: Slice<'s>> Pattern { fn is_select_expr<'s, S: Slice<'s>>(expr: &Expression) -> bool { match expr { Expression::Select { .. } => true, - Expression::Inline(InlineExpression::Placeable { expression }) => { + Expression::Inline(InlineExpression::Placeable { expression, .. }, ..) => { is_select_expr(expression) } - Expression::Inline(_) => false, + Expression::Inline(..) => false, } } @@ -478,12 +485,24 @@ mod test { macro_rules! text_message { ($name:expr, $value:expr) => { Entry::Message(Message { - id: Identifier { name: $name }, + id: Identifier { + name: $name, + #[cfg(feature = "spans")] + span: Span::default(), + }, value: Some(Pattern { - elements: vec![PatternElement::TextElement { value: $value }], + elements: vec![PatternElement::TextElement { + value: $value, + #[cfg(feature = "spans")] + span: Span::default(), + }], + #[cfg(feature = "spans")] + span: Span::default(), }), attributes: vec![], comment: None, + #[cfg(feature = "spans")] + span: Span::default(), }) }; } @@ -506,14 +525,14 @@ mod test { impl<'a> PatternElement<&'a str> { fn as_text(&mut self) -> &mut &'a str { match self { - Self::TextElement { value } => value, + Self::TextElement { value, .. } => value, _ => panic!("Expected TextElement"), } } fn as_expression(&mut self) -> &mut Expression<&'a str> { match self { - Self::Placeable { expression } => expression, + Self::Placeable { expression, .. } => expression, _ => panic!("Expected Placeable"), } } @@ -528,7 +547,7 @@ mod test { } fn as_inline_variable_id(&mut self) -> &mut Identifier<&'a str> { match self { - Self::Inline(InlineExpression::VariableReference { id }) => id, + Self::Inline(InlineExpression::VariableReference { id, .. }, ..) => id, _ => panic!("Expected Inline"), } } @@ -559,18 +578,41 @@ mod test { let mut ast = parse(message).expect("failed to parse ftl resource"); let one_variant = Variant { - key: VariantKey::Identifier { name: "one" }, + key: VariantKey::Identifier { + name: "one", + span: Span::default(), + }, value: Pattern { elements: vec![ PatternElement::Placeable { - expression: Expression::Inline(InlineExpression::VariableReference { - id: Identifier { name: "num" }, - }), + expression: Expression::Inline( + InlineExpression::VariableReference { + id: Identifier { + name: "num", + #[cfg(feature = "spans")] + span: Span::default(), + }, + #[cfg(feature = "spans")] + span: Span::default(), + }, + #[cfg(feature = "spans")] + Span::default(), + ), + #[cfg(feature = "spans")] + span: Span::default(), + }, + PatternElement::TextElement { + value: " bar", + #[cfg(feature = "spans")] + span: Span::default(), }, - PatternElement::TextElement { value: " bar" }, ], + #[cfg(feature = "spans")] + span: Span::default(), }, default: false, + #[cfg(feature = "spans")] + span: Span::default(), }; ast.body[0].as_message().as_pattern().elements[0] .as_expression() @@ -630,6 +672,8 @@ mod test { let mut ast = parse("foo = bar\n").expect("failed to parse ftl resource"); ast.body[0].as_message().comment.replace(Comment { content: vec!["great message!"], + #[cfg(feature = "spans")] + span: Span::default(), }); assert_eq!("# great message!\nfoo = bar\n", serialize(&ast)); } diff --git a/fluent-syntax/tests/serializer_fixtures.rs b/fluent-syntax/tests/serializer_fixtures.rs index 4af214a7..ab5b7225 100644 --- a/fluent-syntax/tests/serializer_fixtures.rs +++ b/fluent-syntax/tests/serializer_fixtures.rs @@ -30,6 +30,8 @@ fn clone_without_junk<'a>(original: &Resource<&'a str>) -> Resource<&'a str> { .filter(|entry| !matches!(entry, Entry::Junk { .. })) .cloned() .collect(), + #[cfg(feature = "spans")] + span: original.span, } } From 57df84d5a06ec93887a28b4d7d093b507c342a42 Mon Sep 17 00:00:00 2001 From: Ertanic Date: Sat, 25 Jan 2025 16:37:54 +0300 Subject: [PATCH 02/11] refactor(fluent-syntax): Derive `PartialEq`, drop manual implementation --- fluent-syntax/src/ast/helper.rs | 31 +--- fluent-syntax/src/ast/mod.rs | 248 +++----------------------------- 2 files changed, 17 insertions(+), 262 deletions(-) diff --git a/fluent-syntax/src/ast/helper.rs b/fluent-syntax/src/ast/helper.rs index 71b5750a..abb2f2f7 100644 --- a/fluent-syntax/src/ast/helper.rs +++ b/fluent-syntax/src/ast/helper.rs @@ -7,8 +7,7 @@ use serde::{Deserialize, Serialize}; // This is a helper struct used to properly deserialize referential // JSON comments which are single continuous String, into a vec of // content slices. -#[derive(Debug, Clone)] -#[cfg_attr(not(feature = "spans"), derive(PartialEq, Eq))] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(untagged))] pub enum CommentDef { @@ -24,34 +23,6 @@ pub enum CommentDef { }, } -#[cfg(feature = "spans")] -impl Eq for CommentDef {} - -#[cfg(feature = "spans")] -impl PartialEq for CommentDef { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - ( - Self::Single { - content: l_content, .. - }, - Self::Single { - content: r_content, .. - }, - ) => l_content == r_content, - ( - Self::Multi { - content: l_content, .. - }, - Self::Multi { - content: r_content, .. - }, - ) => l_content == r_content, - _ => false, - } - } -} - impl From> for Comment { fn from(input: CommentDef) -> Self { match input { diff --git a/fluent-syntax/src/ast/mod.rs b/fluent-syntax/src/ast/mod.rs index ec563484..365eca5d 100644 --- a/fluent-syntax/src/ast/mod.rs +++ b/fluent-syntax/src/ast/mod.rs @@ -113,8 +113,7 @@ use std::ops::Range; /// } /// ); /// ``` -#[derive(Debug, Clone)] -#[cfg_attr(not(feature = "spans"), derive(PartialEq))] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Resource { pub body: Vec>, @@ -122,13 +121,6 @@ pub struct Resource { pub span: Span, } -#[cfg(feature = "spans")] -impl PartialEq for Resource { - fn eq(&self, other: &Self) -> bool { - self.body == other.body - } -} - /// A top-level node representing an entry of a [`Resource`]. /// /// Every [`Entry`] is a standalone element and the parser is capable @@ -205,8 +197,7 @@ impl PartialEq for Resource { /// } /// ); /// ``` -#[derive(Debug, Clone)] -#[cfg_attr(not(feature = "spans"), derive(PartialEq))] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub enum Entry { @@ -222,28 +213,6 @@ pub enum Entry { }, } -#[cfg(feature = "spans")] -impl PartialEq for Entry { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Self::Message(l0), Self::Message(r0)) => l0 == r0, - (Self::Term(l0), Self::Term(r0)) => l0 == r0, - (Self::Comment(l0), Self::Comment(r0)) => l0 == r0, - (Self::GroupComment(l0), Self::GroupComment(r0)) => l0 == r0, - (Self::ResourceComment(l0), Self::ResourceComment(r0)) => l0 == r0, - ( - Self::Junk { - content: l_content, .. - }, - Self::Junk { - content: r_content, .. - }, - ) => l_content == r_content, - _ => false, - } - } -} - /// Message node represents the most common [`Entry`] in an FTL [`Resource`]. /// /// A message is a localization unit with a [`Identifier`] unique within a given @@ -292,7 +261,7 @@ impl PartialEq for Entry { /// } /// ); /// ``` -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Message { pub id: Identifier, @@ -303,15 +272,6 @@ pub struct Message { pub span: Span, } -impl PartialEq for Message { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - && self.value == other.value - && self.attributes == other.attributes - && self.comment == other.comment - } -} - /// A Fluent [`Term`]. /// /// Terms are semantically similar to [`Message`] nodes, but @@ -357,8 +317,7 @@ impl PartialEq for Message { /// } /// ); /// ``` -#[derive(Debug, Clone)] -#[cfg_attr(not(feature = "spans"), derive(PartialEq))] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Term { pub id: Identifier, @@ -369,16 +328,6 @@ pub struct Term { pub span: Span, } -#[cfg(feature = "spans")] -impl PartialEq for Term { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - && self.value == other.value - && self.attributes == other.attributes - && self.comment == other.comment - } -} - /// Pattern contains a value of a [`Message`], [`Term`] or an [`Attribute`]. /// /// Each pattern is a list of [`PatternElement`] nodes representing @@ -450,7 +399,7 @@ impl PartialEq for Term { /// } /// ); /// ``` -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Pattern { pub elements: Vec>, @@ -458,12 +407,6 @@ pub struct Pattern { pub span: Span, } -impl PartialEq for Pattern { - fn eq(&self, other: &Self) -> bool { - self.elements == other.elements - } -} - /// `PatternElement` is an element of a [`Pattern`]. /// /// Each [`PatternElement`] node represents @@ -535,7 +478,7 @@ impl PartialEq for Pattern { /// } /// ); /// ``` -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub enum PatternElement { @@ -551,28 +494,6 @@ pub enum PatternElement { }, } -impl PartialEq for PatternElement { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - ( - Self::TextElement { value: l_value, .. }, - Self::TextElement { value: r_value, .. }, - ) => l_value == r_value, - ( - Self::Placeable { - expression: l_expression, - .. - }, - Self::Placeable { - expression: r_expression, - .. - }, - ) => l_expression == r_expression, - _ => false, - } - } -} - /// Attribute represents a part of a [`Message`] or [`Term`]. /// /// Attributes are used to express a compound list of keyed @@ -636,8 +557,7 @@ impl PartialEq for PatternElement { /// } /// ); /// ``` -#[derive(Debug, Clone)] -#[cfg_attr(not(feature = "spans"), derive(PartialEq))] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Attribute { pub id: Identifier, @@ -646,13 +566,6 @@ pub struct Attribute { pub span: Span, } -#[cfg(feature = "spans")] -impl PartialEq for Attribute { - fn eq(&self, other: &Self) -> bool { - self.id == other.id && self.value == other.value - } -} - /// Identifier is part of nodes such as [`Message`], [`Term`] and [`Attribute`]. /// /// It is used to associate a unique key with an [`Entry`] or an [`Attribute`] @@ -695,7 +608,7 @@ impl PartialEq for Attribute { /// } /// ); /// ``` -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Identifier { pub name: S, @@ -703,14 +616,6 @@ pub struct Identifier { pub span: Span, } -impl Eq for Identifier {} - -impl PartialEq for Identifier { - fn eq(&self, other: &Self) -> bool { - self.name == other.name - } -} - /// Variant is a single branch of a value in a [`Select`](Expression::Select) expression. /// /// It's a pair of [`VariantKey`] and [`Pattern`]. If the selector match the @@ -788,8 +693,7 @@ impl PartialEq for Identifier { /// } /// ); /// ``` -#[derive(Debug, Clone)] -#[cfg_attr(not(feature = "spans"), derive(PartialEq))] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub struct Variant { @@ -800,13 +704,6 @@ pub struct Variant { pub span: Span, } -#[cfg(feature = "spans")] -impl PartialEq for Variant { - fn eq(&self, other: &Self) -> bool { - self.key == other.key && self.value == other.value && self.default == other.default - } -} - /// A key of a [`Variant`]. /// /// Variant key can be either an identifier or a number. @@ -883,7 +780,7 @@ impl PartialEq for Variant { /// } /// ); /// ``` -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub enum VariantKey { @@ -937,7 +834,7 @@ pub enum VariantKey { /// } /// ); /// ``` -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(from = "helper::CommentDef"))] pub struct Comment { @@ -946,14 +843,6 @@ pub struct Comment { pub span: Span, } -impl Eq for Comment {} - -impl PartialEq for Comment { - fn eq(&self, other: &Self) -> bool { - self.content == other.content - } -} - /// List of arguments for a [`FunctionReference`](InlineExpression::FunctionReference) or a /// [`TermReference`](InlineExpression::TermReference). /// @@ -1028,7 +917,7 @@ impl PartialEq for Comment { /// } /// ); /// ``` -#[derive(Debug, Clone, Default)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub struct CallArguments { @@ -1038,12 +927,6 @@ pub struct CallArguments { pub span: Span, } -impl PartialEq for CallArguments { - fn eq(&self, other: &Self) -> bool { - self.positional == other.positional && self.named == other.named - } -} - /// A key-value pair used in [`CallArguments`]. /// /// # Example @@ -1105,8 +988,7 @@ impl PartialEq for CallArguments { /// } /// ); /// ``` -#[derive(Debug, Clone)] -#[cfg_attr(not(feature = "spans"), derive(PartialEq))] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub struct NamedArgument { @@ -1116,13 +998,6 @@ pub struct NamedArgument { pub span: Span, } -#[cfg(feature = "spans")] -impl PartialEq for NamedArgument { - fn eq(&self, other: &Self) -> bool { - self.name == other.name && self.value == other.value - } -} - /// A subset of expressions which can be used as [`Placeable`](PatternElement::Placeable), /// [`selector`](Expression::Select), or in [`CallArguments`]. /// @@ -1171,7 +1046,7 @@ impl PartialEq for NamedArgument { /// } /// ); /// ``` -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] pub enum InlineExpression { @@ -1549,74 +1424,6 @@ pub enum InlineExpression { }, } -impl PartialEq for InlineExpression { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - ( - Self::StringLiteral { value: l_value, .. }, - Self::StringLiteral { value: r_value, .. }, - ) => l_value == r_value, - ( - Self::NumberLiteral { value: l_value, .. }, - Self::NumberLiteral { value: r_value, .. }, - ) => l_value == r_value, - ( - Self::FunctionReference { - id: l_id, - arguments: l_arguments, - .. - }, - Self::FunctionReference { - id: r_id, - arguments: r_arguments, - .. - }, - ) => l_id == r_id && l_arguments == r_arguments, - ( - Self::MessageReference { - id: l_id, - attribute: l_attribute, - .. - }, - Self::MessageReference { - id: r_id, - attribute: r_attribute, - .. - }, - ) => l_id == r_id && l_attribute == r_attribute, - ( - Self::TermReference { - id: l_id, - attribute: l_attribute, - arguments: l_arguments, - .. - }, - Self::TermReference { - id: r_id, - attribute: r_attribute, - arguments: r_arguments, - .. - }, - ) => l_id == r_id && l_attribute == r_attribute && l_arguments == r_arguments, - ( - Self::VariableReference { id: l_id, .. }, - Self::VariableReference { id: r_id, .. }, - ) => l_id == r_id, - ( - Self::Placeable { - expression: l_expression, - .. - }, - Self::Placeable { - expression: r_expression, - .. - }, - ) => l_expression == r_expression, - _ => false, - } - } -} - #[cfg(feature = "spans")] impl InlineExpression { pub fn get_span(&self) -> Span { @@ -1706,8 +1513,7 @@ impl InlineExpression { /// } /// ); /// ``` -#[derive(Debug, Clone)] -#[cfg_attr(not(feature = "spans"), derive(PartialEq))] +#[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(untagged))] pub enum Expression { @@ -1733,28 +1539,6 @@ pub enum Expression { Inline(InlineExpression, #[cfg(feature = "spans")] Span), } -#[cfg(feature = "spans")] -impl PartialEq for Expression { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - ( - Self::Select { - selector: l_selector, - variants: l_variants, - .. - }, - Self::Select { - selector: r_selector, - variants: r_variants, - .. - }, - ) => l_selector == r_selector && l_variants == r_variants, - (Self::Inline(l0, ..), Self::Inline(r0, ..)) => l0 == r0, - _ => false, - } - } -} - /// A span of a node. Allows you to get the index of the start and end character of a node. /// /// # Example @@ -1774,7 +1558,7 @@ impl PartialEq for Expression { /// assert_eq!(id.span, Span { start: 0, end: 11 }); // the span of hello-world identifier /// ``` #[cfg(feature = "spans")] -#[derive(Debug, Clone, Copy, Default, PartialEq)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Span { pub start: usize, From 0756bd1dfbe6b7b7ca94241a8dcf83c6aad3d10d Mon Sep 17 00:00:00 2001 From: Ertanic Date: Sat, 25 Jan 2025 16:37:54 +0300 Subject: [PATCH 03/11] refactor(fluent-syntax): Use pre-formatted messages for `roundtrip_unnormalized_fixtures()` ...and compare with expected span data. --- .gitattributes | 4 +- .../tests/fixtures/formatted/any_char.ftl | 6 ++ .../tests/fixtures/formatted/astral.ftl | 14 ++++ .../fixtures/formatted/call_expressions.ftl | 56 +++++++++++++++ .../fixtures/formatted/callee_expressions.ftl | 36 ++++++++++ .../tests/fixtures/formatted/comments.ftl | 22 ++++++ fluent-syntax/tests/fixtures/formatted/cr.ftl | 2 + .../tests/fixtures/formatted/eof_comment.ftl | 5 ++ .../tests/fixtures/formatted/eof_empty.ftl | 0 .../tests/fixtures/formatted/eof_id.ftl | 2 + .../fixtures/formatted/eof_id_equals.ftl | 2 + .../tests/fixtures/formatted/eof_junk.ftl | 2 + .../tests/fixtures/formatted/eof_value.ftl | 3 + .../fixtures/formatted/escaped_characters.ftl | 38 ++++++++++ .../tests/fixtures/formatted/junk.ftl | 16 +++++ .../fixtures/formatted/junked/any_char.ftl | 6 ++ .../fixtures/formatted/junked/astral.ftl | 21 ++++++ .../formatted/junked/call_expressions.ftl | 71 +++++++++++++++++++ .../formatted/junked/callee_expressions.ftl | 58 +++++++++++++++ .../fixtures/formatted/junked/comments.ftl | 25 +++++++ .../tests/fixtures/formatted/junked/cr.ftl | 2 + .../fixtures/formatted/junked/eof_comment.ftl | 5 ++ .../fixtures/formatted/junked/eof_empty.ftl | 0 .../fixtures/formatted/junked/eof_id.ftl | 3 + .../formatted/junked/eof_id_equals.ftl | 3 + .../fixtures/formatted/junked/eof_junk.ftl | 3 + .../fixtures/formatted/junked/eof_value.ftl | 3 + .../formatted/junked/escaped_characters.ftl | 46 ++++++++++++ .../tests/fixtures/formatted/junked/junk.ftl | 28 ++++++++ .../formatted/junked/leading_dots.ftl | 70 ++++++++++++++++++ .../formatted/junked/literal_expressions.ftl | 3 + .../formatted/junked/member_expressions.ftl | 23 ++++++ .../fixtures/formatted/junked/messages.ftl | 45 ++++++++++++ .../formatted/junked/mixed_entries.ftl | 24 +++++++ .../fixtures/formatted/junked/numbers.ftl | 32 +++++++++ .../fixtures/formatted/junked/obsolete.ftl | 29 ++++++++ .../fixtures/formatted/junked/placeables.ftl | 19 +++++ .../junked/reference_expressions.ftl | 32 +++++++++ .../formatted/junked/select_expressions.ftl | 68 ++++++++++++++++++ .../formatted/junked/select_indent.ftl | 70 ++++++++++++++++++ .../formatted/junked/sparse_entries.ftl | 17 +++++ .../formatted/junked/special_chars.ftl | 14 ++++ .../tests/fixtures/formatted/junked/tab.ftl | 21 ++++++ .../formatted/junked/term_parameters.ftl | 8 +++ .../tests/fixtures/formatted/junked/terms.ftl | 32 +++++++++ .../fixtures/formatted/junked/variables.ftl | 17 +++++ .../formatted/junked/variant_keys.ftl | 37 ++++++++++ .../formatted/junked/whitespace_in_value.ftl | 10 +++ .../fixtures/formatted/junked/zero_length.ftl | 0 .../tests/fixtures/formatted/leading_dots.ftl | 46 ++++++++++++ .../formatted/literal_expressions.ftl | 3 + .../fixtures/formatted/member_expressions.ftl | 17 +++++ .../tests/fixtures/formatted/messages.ftl | 36 ++++++++++ .../fixtures/formatted/mixed_entries.ftl | 19 +++++ .../tests/fixtures/formatted/numbers.ftl | 25 +++++++ .../tests/fixtures/formatted/obsolete.ftl | 9 +++ .../tests/fixtures/formatted/placeables.ftl | 12 ++++ .../formatted/reference_expressions.ftl | 23 ++++++ .../fixtures/formatted/select_expressions.ftl | 38 ++++++++++ .../fixtures/formatted/select_indent.ftl | 65 +++++++++++++++++ .../fixtures/formatted/sparse_entries.ftl | 17 +++++ .../fixtures/formatted/special_chars.ftl | 8 +++ .../tests/fixtures/formatted/tab.ftl | 14 ++++ .../fixtures/formatted/term_parameters.ftl | 8 +++ .../tests/fixtures/formatted/terms.ftl | 20 ++++++ .../tests/fixtures/formatted/variables.ftl | 14 ++++ .../tests/fixtures/formatted/variant_keys.ftl | 23 ++++++ .../formatted/whitespace_in_value.ftl | 10 +++ .../tests/fixtures/formatted/zero_length.ftl | 0 fluent-syntax/tests/serializer_fixtures.rs | 38 +++++----- 70 files changed, 1480 insertions(+), 18 deletions(-) create mode 100644 fluent-syntax/tests/fixtures/formatted/any_char.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/astral.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/call_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/callee_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/comments.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/cr.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/eof_comment.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/eof_empty.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/eof_id.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/eof_id_equals.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/eof_junk.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/eof_value.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/escaped_characters.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junk.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/any_char.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/astral.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/call_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/callee_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/comments.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/cr.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_comment.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_empty.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_id.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_id_equals.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_junk.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_value.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/escaped_characters.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/junk.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/leading_dots.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/literal_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/member_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/messages.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/mixed_entries.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/numbers.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/obsolete.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/placeables.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/reference_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/select_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/select_indent.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/sparse_entries.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/special_chars.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/tab.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/term_parameters.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/terms.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/variables.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/variant_keys.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/whitespace_in_value.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/junked/zero_length.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/leading_dots.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/literal_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/member_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/messages.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/mixed_entries.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/numbers.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/obsolete.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/placeables.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/reference_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/select_expressions.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/select_indent.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/sparse_entries.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/special_chars.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/tab.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/term_parameters.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/terms.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/variables.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/variant_keys.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/whitespace_in_value.ftl create mode 100644 fluent-syntax/tests/fixtures/formatted/zero_length.ftl diff --git a/.gitattributes b/.gitattributes index dcefbe38..00ae28f9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,6 @@ *.ftl eol=lf -fluent-syntax/tests/fixtures/crlf.ftl eol=crlf fluent-syntax/tests/fixtures/cr.ftl eol=cr +fluent-syntax/tests/fixtures/crlf.ftl eol=crlf +fluent-syntax/tests/fixtures/formatted/cr.ftl eol=cr +fluent-syntax/tests/fixtures/formatted/junked/cr.ftl eol=cr diff --git a/fluent-syntax/tests/fixtures/formatted/any_char.ftl b/fluent-syntax/tests/fixtures/formatted/any_char.ftl new file mode 100644 index 00000000..76a1839b --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/any_char.ftl @@ -0,0 +1,6 @@ +# ↓ BEL, U+0007 +control0 = abcdef +# ↓ DEL, U+007F +delete = abcdef +# ↓ BPM, U+0082 +control1 = abc‚def diff --git a/fluent-syntax/tests/fixtures/formatted/astral.ftl b/fluent-syntax/tests/fixtures/formatted/astral.ftl new file mode 100644 index 00000000..f650be0f --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/astral.ftl @@ -0,0 +1,14 @@ +face-with-tears-of-joy = 😂 +tetragram-for-centre = 𝌆 +surrogates-in-text = \uD83D\uDE02 +surrogates-in-string = { "\uD83D\uDE02" } +surrogates-in-adjacent-strings = { "\uD83D" }{ "\uDE02" } +emoji-in-text = A face 😂 with tears of joy. +emoji-in-string = { "A face 😂 with tears of joy." } + +# ERROR Invalid identifier + +# ERROR Invalid expression + +# ERROR Invalid variant key + diff --git a/fluent-syntax/tests/fixtures/formatted/call_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/call_expressions.ftl new file mode 100644 index 00000000..ffef8dca --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/call_expressions.ftl @@ -0,0 +1,56 @@ +## Function names + +valid-func-name-01 = { FUN1() } +valid-func-name-02 = { FUN_FUN() } +valid-func-name-03 = { FUN-FUN() } + +# JUNK 0 is not a valid Identifier start + +# JUNK Function names may not be lowercase + +# JUNK Function names may not contain lowercase character + +# JUNK ? is not a valid Identifier character + +## Arguments + +positional-args = { FUN(1, "a", msg) } +named-args = { FUN(x: 1, y: "Y") } +dense-named-args = { FUN(x: 1, y: "Y") } +mixed-args = { FUN(1, "a", msg, x: 1, y: "Y") } + +# ERROR Positional arg must not follow keyword args + +# ERROR Named arguments must be unique + +## Whitespace around arguments + +sparse-inline-call = { FUN("a", msg, x: 1) } +empty-inline-call = { FUN() } +multiline-call = { FUN("a", msg, x: 1) } +sparse-multiline-call = { FUN("a", msg, x: 1) } +empty-multiline-call = { FUN() } +unindented-arg-number = { FUN(1) } +unindented-arg-string = { FUN("a") } +unindented-arg-msg-ref = { FUN(msg) } +unindented-arg-term-ref = { FUN(-msg) } +unindented-arg-var-ref = { FUN($var) } +unindented-arg-call = { FUN(OTHER()) } +unindented-named-arg = { FUN(x: 1) } +unindented-closing-paren = { FUN(x) } + +## Optional trailing comma + +one-argument = { FUN(1) } +many-arguments = { FUN(1, 2, 3) } +inline-sparse-args = { FUN(1, 2, 3) } +mulitline-args = { FUN(1, 2) } +mulitline-sparse-args = { FUN(1, 2) } + +## Syntax errors for trailing comma + +## Whitespace in named arguments + +sparse-named-arg = { FUN(x: 1, y: 2, z: 3) } +unindented-colon = { FUN(x: 1) } +unindented-value = { FUN(x: 1) } diff --git a/fluent-syntax/tests/fixtures/formatted/callee_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/callee_expressions.ftl new file mode 100644 index 00000000..edc68ab5 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/callee_expressions.ftl @@ -0,0 +1,36 @@ +## Callees in placeables. + +function-callee-placeable = { FUNCTION() } +term-callee-placeable = { -term() } + +# ERROR Messages cannot be parameterized. + +# ERROR Equivalent to a MessageReference callee. + +# ERROR Message attributes cannot be parameterized. + +# ERROR Term attributes may not be used in Placeables. + +# ERROR Variables cannot be parameterized. + +## Callees in selectors. + +function-callee-selector = + { FUNCTION() -> + *[key] Value + } +term-attr-callee-selector = + { -term.attr() -> + *[key] Value + } + +# ERROR Messages cannot be parameterized. + +# ERROR Equivalent to a MessageReference callee. + +# ERROR Message attributes cannot be parameterized. + +# ERROR Term values may not be used as selectors. + +# ERROR Variables cannot be parameterized. + diff --git a/fluent-syntax/tests/fixtures/formatted/comments.ftl b/fluent-syntax/tests/fixtures/formatted/comments.ftl new file mode 100644 index 00000000..45754cd9 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/comments.ftl @@ -0,0 +1,22 @@ +# Standalone Comment + +# Message Comment +foo = Foo +# Term Comment +# with a blank last line. +# +-term = Term + +# Another standalone +# +# with indent + + +## Group Comment + + +### Resource Comment + + +# Errors + diff --git a/fluent-syntax/tests/fixtures/formatted/cr.ftl b/fluent-syntax/tests/fixtures/formatted/cr.ftl new file mode 100644 index 00000000..ace98efb --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/cr.ftl @@ -0,0 +1,2 @@ +### This entire file uses CR as EOL. err01 = Value 01 err02 = Value 02 err03 = Value 03 Continued .title = Title err04 = { "str err05 = { $sel -> } + diff --git a/fluent-syntax/tests/fixtures/formatted/eof_comment.ftl b/fluent-syntax/tests/fixtures/formatted/eof_comment.ftl new file mode 100644 index 00000000..d262c3b3 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/eof_comment.ftl @@ -0,0 +1,5 @@ +### NOTE: Disable final newline insertion when editing this file. + + +# No EOL + diff --git a/fluent-syntax/tests/fixtures/formatted/eof_empty.ftl b/fluent-syntax/tests/fixtures/formatted/eof_empty.ftl new file mode 100644 index 00000000..e69de29b diff --git a/fluent-syntax/tests/fixtures/formatted/eof_id.ftl b/fluent-syntax/tests/fixtures/formatted/eof_id.ftl new file mode 100644 index 00000000..c938b0bc --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/eof_id.ftl @@ -0,0 +1,2 @@ +### NOTE: Disable final newline insertion when editing this file. + diff --git a/fluent-syntax/tests/fixtures/formatted/eof_id_equals.ftl b/fluent-syntax/tests/fixtures/formatted/eof_id_equals.ftl new file mode 100644 index 00000000..c938b0bc --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/eof_id_equals.ftl @@ -0,0 +1,2 @@ +### NOTE: Disable final newline insertion when editing this file. + diff --git a/fluent-syntax/tests/fixtures/formatted/eof_junk.ftl b/fluent-syntax/tests/fixtures/formatted/eof_junk.ftl new file mode 100644 index 00000000..c938b0bc --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/eof_junk.ftl @@ -0,0 +1,2 @@ +### NOTE: Disable final newline insertion when editing this file. + diff --git a/fluent-syntax/tests/fixtures/formatted/eof_value.ftl b/fluent-syntax/tests/fixtures/formatted/eof_value.ftl new file mode 100644 index 00000000..23ee1b60 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/eof_value.ftl @@ -0,0 +1,3 @@ +### NOTE: Disable final newline insertion when editing this file. + +no-eol = No EOL diff --git a/fluent-syntax/tests/fixtures/formatted/escaped_characters.ftl b/fluent-syntax/tests/fixtures/formatted/escaped_characters.ftl new file mode 100644 index 00000000..29c56f50 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/escaped_characters.ftl @@ -0,0 +1,38 @@ +## Literal text + +text-backslash-one = Value with \ a backslash +text-backslash-two = Value with \\ two backslashes +text-backslash-brace = Value with \{ placeable } +text-backslash-u = \u0041 +text-backslash-backslash-u = \\u0041 + +## String literals + +quote-in-string = { "\"" } +backslash-in-string = { "\\" } + +# ERROR Mismatched quote + +# ERROR Unknown escape + +# ERROR Multiline literal + +## Unicode escapes + +string-unicode-4digits = { "\u0041" } +escape-unicode-4digits = { "\\u0041" } +string-unicode-6digits = { "\U01F602" } +escape-unicode-6digits = { "\\U01F602" } +# OK The trailing "00" is part of the literal value. +string-too-many-4digits = { "\u004100" } +# OK The trailing "00" is part of the literal value. +string-too-many-6digits = { "\U01F60200" } + +# ERROR Too few hex digits after \u. + +# ERROR Too few hex digits after \U. + +## Literal braces + +brace-open = An opening { "{" } brace. +brace-close = A closing { "}" } brace. diff --git a/fluent-syntax/tests/fixtures/formatted/junk.ftl b/fluent-syntax/tests/fixtures/formatted/junk.ftl new file mode 100644 index 00000000..d0ff0158 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junk.ftl @@ -0,0 +1,16 @@ +## Two adjacent Junks. + +# A single Junk. + +# A single Junk. + +# The COMMENT ends this junk. + +# COMMENT + + +# The COMMENT ends this junk. +# The closing brace is a separate Junk. + +# COMMENT + diff --git a/fluent-syntax/tests/fixtures/formatted/junked/any_char.ftl b/fluent-syntax/tests/fixtures/formatted/junked/any_char.ftl new file mode 100644 index 00000000..76a1839b --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/any_char.ftl @@ -0,0 +1,6 @@ +# ↓ BEL, U+0007 +control0 = abcdef +# ↓ DEL, U+007F +delete = abcdef +# ↓ BPM, U+0082 +control1 = abc‚def diff --git a/fluent-syntax/tests/fixtures/formatted/junked/astral.ftl b/fluent-syntax/tests/fixtures/formatted/junked/astral.ftl new file mode 100644 index 00000000..f29fef0a --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/astral.ftl @@ -0,0 +1,21 @@ +face-with-tears-of-joy = 😂 +tetragram-for-centre = 𝌆 +surrogates-in-text = \uD83D\uDE02 +surrogates-in-string = { "\uD83D\uDE02" } +surrogates-in-adjacent-strings = { "\uD83D" }{ "\uDE02" } +emoji-in-text = A face 😂 with tears of joy. +emoji-in-string = { "A face 😂 with tears of joy." } + +# ERROR Invalid identifier + +err-😂 = Value + +# ERROR Invalid expression + +err-invalid-expression = { 😂 } + +# ERROR Invalid variant key + +err-invalid-variant-key = { $sel -> + *[😂] Value +} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/call_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/call_expressions.ftl new file mode 100644 index 00000000..46a531fe --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/call_expressions.ftl @@ -0,0 +1,71 @@ +## Function names + +valid-func-name-01 = { FUN1() } +valid-func-name-02 = { FUN_FUN() } +valid-func-name-03 = { FUN-FUN() } + +# JUNK 0 is not a valid Identifier start + +invalid-func-name-01 = {0FUN()} +# JUNK Function names may not be lowercase + +invalid-func-name-02 = {fun()} +# JUNK Function names may not contain lowercase character + +invalid-func-name-03 = {Fun()} +# JUNK ? is not a valid Identifier character + +invalid-func-name-04 = {FUN?()} + +## Arguments + +positional-args = { FUN(1, "a", msg) } +named-args = { FUN(x: 1, y: "Y") } +dense-named-args = { FUN(x: 1, y: "Y") } +mixed-args = { FUN(1, "a", msg, x: 1, y: "Y") } + +# ERROR Positional arg must not follow keyword args + +shuffled-args = {FUN(1, x: 1, "a", y: "Y", msg)} + +# ERROR Named arguments must be unique + +duplicate-named-args = {FUN(x: 1, x: "X")} + + +## Whitespace around arguments + +sparse-inline-call = { FUN("a", msg, x: 1) } +empty-inline-call = { FUN() } +multiline-call = { FUN("a", msg, x: 1) } +sparse-multiline-call = { FUN("a", msg, x: 1) } +empty-multiline-call = { FUN() } +unindented-arg-number = { FUN(1) } +unindented-arg-string = { FUN("a") } +unindented-arg-msg-ref = { FUN(msg) } +unindented-arg-term-ref = { FUN(-msg) } +unindented-arg-var-ref = { FUN($var) } +unindented-arg-call = { FUN(OTHER()) } +unindented-named-arg = { FUN(x: 1) } +unindented-closing-paren = { FUN(x) } + +## Optional trailing comma + +one-argument = { FUN(1) } +many-arguments = { FUN(1, 2, 3) } +inline-sparse-args = { FUN(1, 2, 3) } +mulitline-args = { FUN(1, 2) } +mulitline-sparse-args = { FUN(1, 2) } + +## Syntax errors for trailing comma + +one-argument = {FUN(1,,)} +missing-arg = {FUN(,)} +missing-sparse-arg = {FUN( , )} + + +## Whitespace in named arguments + +sparse-named-arg = { FUN(x: 1, y: 2, z: 3) } +unindented-colon = { FUN(x: 1) } +unindented-value = { FUN(x: 1) } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/callee_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/callee_expressions.ftl new file mode 100644 index 00000000..ca98eae7 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/callee_expressions.ftl @@ -0,0 +1,58 @@ +## Callees in placeables. + +function-callee-placeable = { FUNCTION() } +term-callee-placeable = { -term() } + +# ERROR Messages cannot be parameterized. + +message-callee-placeable = {message()} +# ERROR Equivalent to a MessageReference callee. + +mixed-case-callee-placeable = {Function()} +# ERROR Message attributes cannot be parameterized. + +message-attr-callee-placeable = {message.attr()} +# ERROR Term attributes may not be used in Placeables. + +term-attr-callee-placeable = {-term.attr()} +# ERROR Variables cannot be parameterized. + +variable-callee-placeable = {$variable()} + + +## Callees in selectors. + +function-callee-selector = + { FUNCTION() -> + *[key] Value + } +term-attr-callee-selector = + { -term.attr() -> + *[key] Value + } + +# ERROR Messages cannot be parameterized. + +message-callee-selector = {message() -> + *[key] Value +} +# ERROR Equivalent to a MessageReference callee. + +mixed-case-callee-selector = {Function() -> + *[key] Value +} +# ERROR Message attributes cannot be parameterized. + +message-attr-callee-selector = {message.attr() -> + *[key] Value +} +# ERROR Term values may not be used as selectors. + +term-callee-selector = {-term() -> + *[key] Value +} +# ERROR Variables cannot be parameterized. + +variable-callee-selector = {$variable() -> + *[key] Value +} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/comments.ftl b/fluent-syntax/tests/fixtures/formatted/junked/comments.ftl new file mode 100644 index 00000000..be10bad2 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/comments.ftl @@ -0,0 +1,25 @@ +# Standalone Comment + +# Message Comment +foo = Foo +# Term Comment +# with a blank last line. +# +-term = Term + +# Another standalone +# +# with indent + + +## Group Comment + + +### Resource Comment + + +# Errors + +#error +##error +###error diff --git a/fluent-syntax/tests/fixtures/formatted/junked/cr.ftl b/fluent-syntax/tests/fixtures/formatted/junked/cr.ftl new file mode 100644 index 00000000..ace98efb --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/cr.ftl @@ -0,0 +1,2 @@ +### This entire file uses CR as EOL. err01 = Value 01 err02 = Value 02 err03 = Value 03 Continued .title = Title err04 = { "str err05 = { $sel -> } + diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_comment.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_comment.ftl new file mode 100644 index 00000000..d262c3b3 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/eof_comment.ftl @@ -0,0 +1,5 @@ +### NOTE: Disable final newline insertion when editing this file. + + +# No EOL + diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_empty.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_empty.ftl new file mode 100644 index 00000000..e69de29b diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_id.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_id.ftl new file mode 100644 index 00000000..63fa86d6 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/eof_id.ftl @@ -0,0 +1,3 @@ +### NOTE: Disable final newline insertion when editing this file. + +message-id \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_id_equals.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_id_equals.ftl new file mode 100644 index 00000000..7d0d953a --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/eof_id_equals.ftl @@ -0,0 +1,3 @@ +### NOTE: Disable final newline insertion when editing this file. + +message-id = \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_junk.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_junk.ftl new file mode 100644 index 00000000..dbafd3a3 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/eof_junk.ftl @@ -0,0 +1,3 @@ +### NOTE: Disable final newline insertion when editing this file. + +000 \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_value.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_value.ftl new file mode 100644 index 00000000..23ee1b60 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/eof_value.ftl @@ -0,0 +1,3 @@ +### NOTE: Disable final newline insertion when editing this file. + +no-eol = No EOL diff --git a/fluent-syntax/tests/fixtures/formatted/junked/escaped_characters.ftl b/fluent-syntax/tests/fixtures/formatted/junked/escaped_characters.ftl new file mode 100644 index 00000000..b6025b76 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/escaped_characters.ftl @@ -0,0 +1,46 @@ +## Literal text + +text-backslash-one = Value with \ a backslash +text-backslash-two = Value with \\ two backslashes +text-backslash-brace = Value with \{ placeable } +text-backslash-u = \u0041 +text-backslash-backslash-u = \\u0041 + +## String literals + +quote-in-string = { "\"" } +backslash-in-string = { "\\" } + +# ERROR Mismatched quote + +mismatched-quote = {"\\""} +# ERROR Unknown escape + +unknown-escape = {"\x"} +# ERROR Multiline literal + +invalid-multiline-literal = {" + "} + +## Unicode escapes + +string-unicode-4digits = { "\u0041" } +escape-unicode-4digits = { "\\u0041" } +string-unicode-6digits = { "\U01F602" } +escape-unicode-6digits = { "\\U01F602" } +# OK The trailing "00" is part of the literal value. +string-too-many-4digits = { "\u004100" } +# OK The trailing "00" is part of the literal value. +string-too-many-6digits = { "\U01F60200" } + +# ERROR Too few hex digits after \u. + +string-too-few-4digits = {"\u41"} +# ERROR Too few hex digits after \U. + +string-too-few-6digits = {"\U1F602"} + +## Literal braces + +brace-open = An opening { "{" } brace. +brace-close = A closing { "}" } brace. diff --git a/fluent-syntax/tests/fixtures/formatted/junked/junk.ftl b/fluent-syntax/tests/fixtures/formatted/junked/junk.ftl new file mode 100644 index 00000000..6085bb92 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/junk.ftl @@ -0,0 +1,28 @@ +## Two adjacent Junks. + +err01 = {1x} +err02 = {2x} + +# A single Junk. + +err03 = {1x +2 + +# A single Junk. + +ą=Invalid identifier +ć=Another one + +# The COMMENT ends this junk. + +err04 = { +# COMMENT + + +# The COMMENT ends this junk. +# The closing brace is a separate Junk. + +err04 = { +# COMMENT + +} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/leading_dots.ftl b/fluent-syntax/tests/fixtures/formatted/junked/leading_dots.ftl new file mode 100644 index 00000000..e87e4097 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/leading_dots.ftl @@ -0,0 +1,70 @@ +key01 = .Value +key02 = …Value +key03 = { "." }Value +key04 = { "." }Value +key05 = + Value + { "." }Continued +key06 = .Value +{ "." }Continued +# MESSAGE (value = "Value", attributes = []) +# JUNK (attr .Continued" must have a value) +key07 = Value + .Continued + +# JUNK (attr .Value must have a value) + +key08 = + .Value + +# JUNK (attr .Value must have a value) + +key09 = + .Value + Continued + +key10 = + .Value = + which is an attribute + Continued +key11 = + { "." }Value = which looks like an attribute + Continued +key12 = + .accesskey = A +key13 = + .attribute = .Value +key14 = + .attribute = { "." }Value +key15 = + { 1 -> + [one] .Value + *[other] { "." }Value + } + +# JUNK (variant must have a value) + +key16 = + { 1 -> + *[one] + .Value + } + +# JUNK (unclosed placeable) + +key17 = + { 1 -> + *[one] Value + .Continued + } + +# JUNK (attr .Value must have a value) + +key18 = +.Value + +key19 = + .attribute = + Value + Continued +key20 = { "." }Value diff --git a/fluent-syntax/tests/fixtures/formatted/junked/literal_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/literal_expressions.ftl new file mode 100644 index 00000000..8b45c427 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/literal_expressions.ftl @@ -0,0 +1,3 @@ +string-expression = { "abc" } +number-expression = { 123 } +number-expression = { -3.14 } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/member_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/member_expressions.ftl new file mode 100644 index 00000000..3a1089c8 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/member_expressions.ftl @@ -0,0 +1,23 @@ +## Member expressions in placeables. + +# OK Message attributes may be interpolated in values. +message-attribute-expression-placeable = { msg.attr } + +# ERROR Term attributes may not be used for interpolation. + +term-attribute-expression-placeable = {-term.attr} + + +## Member expressions in selectors. + +# OK Term attributes may be used as selectors. +term-attribute-expression-selector = + { -term.attr -> + *[key] Value + } + +# ERROR Message attributes may not be used as selectors. + +message-attribute-expression-selector = {msg.attr -> + *[key] Value +} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/messages.ftl b/fluent-syntax/tests/fixtures/formatted/junked/messages.ftl new file mode 100644 index 00000000..a5bcd1f1 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/messages.ftl @@ -0,0 +1,45 @@ +key01 = Value +key02 = Value + .attr = Attribute +key02 = Value + .attr1 = Attribute 1 + .attr2 = Attribute 2 +key03 = + .attr = Attribute +key04 = + .attr1 = Attribute 1 + .attr2 = Attribute 2 +# < whitespace > +key05 = + .attr1 = Attribute 1 +no-whitespace = Value + .attr1 = Attribute 1 +extra-whitespace = Value + .attr1 = Attribute 1 +key06 = { "" } + +# JUNK Missing value + +key07 = + +# JUNK Missing = + +key08 + +KEY09 = Value 09 +key-10 = Value 10 +key_11 = Value 11 +key-12- = Value 12 +key_13_ = Value 13 + +# JUNK Invalid id + +0err-14 = Value 14 + +# JUNK Invalid id + +err-15? = Value 15 + +# JUNK Invalid id + +err-ąę-16 = Value 16 diff --git a/fluent-syntax/tests/fixtures/formatted/junked/mixed_entries.ftl b/fluent-syntax/tests/fixtures/formatted/junked/mixed_entries.ftl new file mode 100644 index 00000000..57480b45 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/mixed_entries.ftl @@ -0,0 +1,24 @@ +# License Comment + + +### Resource Comment + +-brand-name = Aurora + +## Group Comment + +key01 = + .attr = Attribute +ą=Invalid identifier +ć=Another one + +# Message Comment +key02 = Value + +# Standalone Comment + + .attr = Dangling attribute + +# There are 5 spaces on the line between key03 and key04. +key03 = Value 03 +key04 = Value 04 diff --git a/fluent-syntax/tests/fixtures/formatted/junked/numbers.ftl b/fluent-syntax/tests/fixtures/formatted/junked/numbers.ftl new file mode 100644 index 00000000..08d6e6b1 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/numbers.ftl @@ -0,0 +1,32 @@ +int-zero = { 0 } +int-positive = { 1 } +int-negative = { -1 } +int-negative-zero = { -0 } +int-positive-padded = { 01 } +int-negative-padded = { -01 } +int-zero-padded = { 00 } +int-negative-zero-padded = { -00 } +float-zero = { 0.0 } +float-positive = { 0.01 } +float-positive-one = { 1.03 } +float-positive-without-fraction = { 1.000 } +float-negative = { -0.01 } +float-negative-one = { -1.03 } +float-negative-zero = { -0.0 } +float-negative-without-fraction = { -1.000 } +float-positive-padded-left = { 01.03 } +float-positive-padded-right = { 1.0300 } +float-positive-padded-both = { 01.0300 } +float-negative-padded-left = { -01.03 } +float-negative-padded-right = { -1.0300 } +float-negative-padded-both = { -01.0300 } + +## ERRORS + +err01 = {1.} +err02 = {.02} +err03 = {1.02.03} +err04 = {1. 02} +err05 = {1 .02} +err06 = {- 1} +err07 = {1,02} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/obsolete.ftl b/fluent-syntax/tests/fixtures/formatted/junked/obsolete.ftl new file mode 100644 index 00000000..e0869e3a --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/obsolete.ftl @@ -0,0 +1,29 @@ +### The syntax in this file has been discontinued. It is no longer part of the +### Fluent specification and should not be implemented nor used. We're keeping +### these fixtures around to protect against accidental syntax reuse. + + +## Variant lists. + +message-variant-list = + { + *[key] Value + } + +-term-variant-list = + { + *[key] Value + } + + +## Variant expressions. + +message-variant-expression-placeable = {msg[case]} +message-variant-expression-selector = {msg[case] -> + *[key] Value +} + +term-variant-expression-placeable = {-term[case]} +term-variant-expression-selector = {-term[case] -> + *[key] Value +} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/placeables.ftl b/fluent-syntax/tests/fixtures/formatted/junked/placeables.ftl new file mode 100644 index 00000000..1a2013b9 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/placeables.ftl @@ -0,0 +1,19 @@ +nested-placeable = {{ {1} }} +padded-placeable = { 1 } +sparse-placeable = {{ 1 }} + +# ERROR Unmatched opening brace + +unmatched-open1 = { 1 + +# ERROR Unmatched opening brace + +unmatched-open2 = {{ 1 } + +# ERROR Unmatched closing brace + +unmatched-close1 = 1 } + +# ERROR Unmatched closing brace + +unmatched-close2 = { 1 }} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/reference_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/reference_expressions.ftl new file mode 100644 index 00000000..1f4b8674 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/reference_expressions.ftl @@ -0,0 +1,32 @@ +## Reference expressions in placeables. + +message-reference-placeable = { msg } +term-reference-placeable = { -term } +variable-reference-placeable = { $var } +# Function references are invalid outside of call expressions. +# This parses as a valid MessageReference. +function-reference-placeable = { FUN } + +## Reference expressions in selectors. + +variable-reference-selector = + { $var -> + *[key] Value + } + +# ERROR Message values may not be used as selectors. + +message-reference-selector = {msg -> + *[key] Value +} +# ERROR Term values may not be used as selectors. + +term-reference-selector = {-term -> + *[key] Value +} +# ERROR Function references are invalid outside of call expressions, and this +# parses as a MessageReference which isn't a valid selector. + +function-expression-selector = {FUN -> + *[key] Value +} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/select_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/select_expressions.ftl new file mode 100644 index 00000000..4598442e --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/select_expressions.ftl @@ -0,0 +1,68 @@ +new-messages = + { BUILTIN() -> + [0] Zero + *[other] { "" }Other + } +valid-selector-term-attribute = + { -term.case -> + *[key] value + } + +# ERROR Term values are not valid selectors + +invalid-selector-term-value = + { -term -> + *[key] value + } + +# ERROR CallExpressions on Terms are similar to TermReferences + +invalid-selector-term-variant = + { -term(case: "nominative") -> + *[key] value + } + +# ERROR Nested expressions are not valid selectors + +invalid-selector-nested-expression = + { { 3 } -> + *[key] default + } + +# ERROR Select expressions are not valid selectors + +invalid-selector-select-expression = + { { $sel -> + *[key] value + } -> + *[key] default + } + +empty-variant = + { $sel -> + *[key] { "" } + } +reduced-whitespace = + { FOO() -> + *[key] { "" } + } +nested-select = + { $sel -> + *[one] + { $sel -> + *[two] Value + } + } + +# ERROR Missing selector + +missing-selector = + { + *[key] Value + } + +# ERROR Missing line end after variant list + +missing-line-end = + { $sel -> + *[key] Value} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/select_indent.ftl b/fluent-syntax/tests/fixtures/formatted/junked/select_indent.ftl new file mode 100644 index 00000000..3c21d71f --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/select_indent.ftl @@ -0,0 +1,70 @@ +select-1tbs-inline = + { $selector -> + *[key] Value + } +select-1tbs-newline = + { $selector -> + *[key] Value + } +select-1tbs-indent = + { $selector -> + *[key] Value + } +select-allman-inline = + { $selector -> + *[key] Value + [other] Other + } +select-allman-newline = + { $selector -> + *[key] Value + } +select-allman-indent = + { $selector -> + *[key] Value + } +select-gnu-inline = + { $selector -> + *[key] Value + } +select-gnu-newline = + { $selector -> + *[key] Value + } +select-gnu-indent = + { $selector -> + *[key] Value + } +select-no-indent = + { $selector -> + *[key] Value + [other] Other + } +select-no-indent-multiline = + { $selector -> + *[key] + Value + Continued + [other] + Other + Multiline + } + +# ERROR (Multiline text must be indented) + +select-no-indent-multiline = { $selector -> + *[key] Value +Continued without indent. +} + +select-flat = + { $selector -> + *[key] Value + [other] Other + } +# Each line ends with 5 spaces. +select-flat-with-trailing-spaces = + { $selector -> + *[key] Value + [other] Other + } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/sparse_entries.ftl b/fluent-syntax/tests/fixtures/formatted/junked/sparse_entries.ftl new file mode 100644 index 00000000..dfa85945 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/sparse_entries.ftl @@ -0,0 +1,17 @@ +key01 = Value +key02 = + .attr = Attribute +key03 = + Value + Continued + + + Over multiple + Lines + .attr = Attribute +key05 = Value +key06 = + { 1 -> + [one] One + *[two] Two + } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/special_chars.ftl b/fluent-syntax/tests/fixtures/formatted/junked/special_chars.ftl new file mode 100644 index 00000000..5224bad7 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/special_chars.ftl @@ -0,0 +1,14 @@ +## OK + +bracket-inline = [Value] +dot-inline = .Value +star-inline = *Value + +## ERRORS + +bracket-newline = + [Value] +dot-newline = + .Value +star-newline = + *Value diff --git a/fluent-syntax/tests/fixtures/formatted/junked/tab.ftl b/fluent-syntax/tests/fixtures/formatted/junked/tab.ftl new file mode 100644 index 00000000..46b5aa9f --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/tab.ftl @@ -0,0 +1,21 @@ +# OK (tab after = is part of the value) +key01 = Value 01 + +# Error (tab before =) + +key02 = Value 02 + +# Error (tab is not a valid indent) + +key03 = + This line isn't properly indented. + +# Partial Error (tab is not a valid indent) +key04 = This line is indented by 4 spaces, + whereas this line by 1 tab. + +# OK (value is a single tab) +key05 = +# OK (attribute value is two tabs) +key06 = + .attr = diff --git a/fluent-syntax/tests/fixtures/formatted/junked/term_parameters.ftl b/fluent-syntax/tests/fixtures/formatted/junked/term_parameters.ftl new file mode 100644 index 00000000..8ee2ed74 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/term_parameters.ftl @@ -0,0 +1,8 @@ +-term = + { $arg -> + *[key] Value + } +key01 = { -term } +key02 = { -term() } +key03 = { -term(arg: 1) } +key04 = { -term("positional", narg1: 1, narg2: 2) } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/terms.ftl b/fluent-syntax/tests/fixtures/formatted/junked/terms.ftl new file mode 100644 index 00000000..4bd9e6cc --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/terms.ftl @@ -0,0 +1,32 @@ +-term01 = Value + .attr = Attribute +-term02 = { "" } + +# JUNK Missing value + +-term03 = + .attr = Attribute + +# JUNK Missing value +# < whitespace > + +-term04 = + .attr1 = Attribute 1 + +# JUNK Missing value + +-term05 = + +# JUNK Missing value +# < whitespace > + +-term06 = + +# JUNK Missing = + +-term07 + +-term08 = Value + .attr = Attribute +-term09 = Value + .attr = Attribute diff --git a/fluent-syntax/tests/fixtures/formatted/junked/variables.ftl b/fluent-syntax/tests/fixtures/formatted/junked/variables.ftl new file mode 100644 index 00000000..1a12cc59 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/variables.ftl @@ -0,0 +1,17 @@ +key01 = { $var } +key02 = { $var } +key03 = { $var } +key04 = { $var } + +## Errors + + +# ERROR Missing variable identifier + +err01 = {$} +# ERROR Double $$ + +err02 = {$$var} +# ERROR Invalid first char of the identifier + +err03 = {$-var} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/variant_keys.ftl b/fluent-syntax/tests/fixtures/formatted/junked/variant_keys.ftl new file mode 100644 index 00000000..e3ee17f2 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/variant_keys.ftl @@ -0,0 +1,37 @@ +simple-identifier = + { $sel -> + *[key] value + } +identifier-surrounded-by-whitespace = + { $sel -> + *[key] value + } +int-number = + { $sel -> + *[1] value + } +float-number = + { $sel -> + *[3.14] value + } + +# ERROR + +invalid-identifier = + { $sel -> + *[two words] value + } + +# ERROR + +invalid-int = + { $sel -> + *[1 apple] value + } + +# ERROR + +invalid-int = + { $sel -> + *[3.14 apples] value + } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/whitespace_in_value.ftl b/fluent-syntax/tests/fixtures/formatted/junked/whitespace_in_value.ftl new file mode 100644 index 00000000..0cbcd371 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/junked/whitespace_in_value.ftl @@ -0,0 +1,10 @@ +# Caution, lines 6 and 7 contain white-space-only lines +key = + first line + + + + + + + last line diff --git a/fluent-syntax/tests/fixtures/formatted/junked/zero_length.ftl b/fluent-syntax/tests/fixtures/formatted/junked/zero_length.ftl new file mode 100644 index 00000000..e69de29b diff --git a/fluent-syntax/tests/fixtures/formatted/leading_dots.ftl b/fluent-syntax/tests/fixtures/formatted/leading_dots.ftl new file mode 100644 index 00000000..d63f60e3 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/leading_dots.ftl @@ -0,0 +1,46 @@ +key01 = .Value +key02 = …Value +key03 = { "." }Value +key04 = { "." }Value +key05 = + Value + { "." }Continued +key06 = .Value +{ "." }Continued +# MESSAGE (value = "Value", attributes = []) +# JUNK (attr .Continued" must have a value) +key07 = Value +# JUNK (attr .Value must have a value) + +# JUNK (attr .Value must have a value) + +key10 = + .Value = + which is an attribute + Continued +key11 = + { "." }Value = which looks like an attribute + Continued +key12 = + .accesskey = A +key13 = + .attribute = .Value +key14 = + .attribute = { "." }Value +key15 = + { 1 -> + [one] .Value + *[other] { "." }Value + } + +# JUNK (variant must have a value) + +# JUNK (unclosed placeable) + +# JUNK (attr .Value must have a value) + +key19 = + .attribute = + Value + Continued +key20 = { "." }Value diff --git a/fluent-syntax/tests/fixtures/formatted/literal_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/literal_expressions.ftl new file mode 100644 index 00000000..8b45c427 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/literal_expressions.ftl @@ -0,0 +1,3 @@ +string-expression = { "abc" } +number-expression = { 123 } +number-expression = { -3.14 } diff --git a/fluent-syntax/tests/fixtures/formatted/member_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/member_expressions.ftl new file mode 100644 index 00000000..809c2608 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/member_expressions.ftl @@ -0,0 +1,17 @@ +## Member expressions in placeables. + +# OK Message attributes may be interpolated in values. +message-attribute-expression-placeable = { msg.attr } + +# ERROR Term attributes may not be used for interpolation. + +## Member expressions in selectors. + +# OK Term attributes may be used as selectors. +term-attribute-expression-selector = + { -term.attr -> + *[key] Value + } + +# ERROR Message attributes may not be used as selectors. + diff --git a/fluent-syntax/tests/fixtures/formatted/messages.ftl b/fluent-syntax/tests/fixtures/formatted/messages.ftl new file mode 100644 index 00000000..72403bd3 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/messages.ftl @@ -0,0 +1,36 @@ +key01 = Value +key02 = Value + .attr = Attribute +key02 = Value + .attr1 = Attribute 1 + .attr2 = Attribute 2 +key03 = + .attr = Attribute +key04 = + .attr1 = Attribute 1 + .attr2 = Attribute 2 +# < whitespace > +key05 = + .attr1 = Attribute 1 +no-whitespace = Value + .attr1 = Attribute 1 +extra-whitespace = Value + .attr1 = Attribute 1 +key06 = { "" } + +# JUNK Missing value + +# JUNK Missing = + +KEY09 = Value 09 +key-10 = Value 10 +key_11 = Value 11 +key-12- = Value 12 +key_13_ = Value 13 + +# JUNK Invalid id + +# JUNK Invalid id + +# JUNK Invalid id + diff --git a/fluent-syntax/tests/fixtures/formatted/mixed_entries.ftl b/fluent-syntax/tests/fixtures/formatted/mixed_entries.ftl new file mode 100644 index 00000000..f8e54c29 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/mixed_entries.ftl @@ -0,0 +1,19 @@ +# License Comment + + +### Resource Comment + +-brand-name = Aurora + +## Group Comment + +key01 = + .attr = Attribute +# Message Comment +key02 = Value + +# Standalone Comment + +# There are 5 spaces on the line between key03 and key04. +key03 = Value 03 +key04 = Value 04 diff --git a/fluent-syntax/tests/fixtures/formatted/numbers.ftl b/fluent-syntax/tests/fixtures/formatted/numbers.ftl new file mode 100644 index 00000000..521f5a23 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/numbers.ftl @@ -0,0 +1,25 @@ +int-zero = { 0 } +int-positive = { 1 } +int-negative = { -1 } +int-negative-zero = { -0 } +int-positive-padded = { 01 } +int-negative-padded = { -01 } +int-zero-padded = { 00 } +int-negative-zero-padded = { -00 } +float-zero = { 0.0 } +float-positive = { 0.01 } +float-positive-one = { 1.03 } +float-positive-without-fraction = { 1.000 } +float-negative = { -0.01 } +float-negative-one = { -1.03 } +float-negative-zero = { -0.0 } +float-negative-without-fraction = { -1.000 } +float-positive-padded-left = { 01.03 } +float-positive-padded-right = { 1.0300 } +float-positive-padded-both = { 01.0300 } +float-negative-padded-left = { -01.03 } +float-negative-padded-right = { -1.0300 } +float-negative-padded-both = { -01.0300 } + +## ERRORS + diff --git a/fluent-syntax/tests/fixtures/formatted/obsolete.ftl b/fluent-syntax/tests/fixtures/formatted/obsolete.ftl new file mode 100644 index 00000000..314a35ef --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/obsolete.ftl @@ -0,0 +1,9 @@ +### The syntax in this file has been discontinued. It is no longer part of the +### Fluent specification and should not be implemented nor used. We're keeping +### these fixtures around to protect against accidental syntax reuse. + + +## Variant lists. + +## Variant expressions. + diff --git a/fluent-syntax/tests/fixtures/formatted/placeables.ftl b/fluent-syntax/tests/fixtures/formatted/placeables.ftl new file mode 100644 index 00000000..6a5167be --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/placeables.ftl @@ -0,0 +1,12 @@ +nested-placeable = {{ {1} }} +padded-placeable = { 1 } +sparse-placeable = {{ 1 }} + +# ERROR Unmatched opening brace + +# ERROR Unmatched opening brace + +# ERROR Unmatched closing brace + +# ERROR Unmatched closing brace + diff --git a/fluent-syntax/tests/fixtures/formatted/reference_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/reference_expressions.ftl new file mode 100644 index 00000000..5132517f --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/reference_expressions.ftl @@ -0,0 +1,23 @@ +## Reference expressions in placeables. + +message-reference-placeable = { msg } +term-reference-placeable = { -term } +variable-reference-placeable = { $var } +# Function references are invalid outside of call expressions. +# This parses as a valid MessageReference. +function-reference-placeable = { FUN } + +## Reference expressions in selectors. + +variable-reference-selector = + { $var -> + *[key] Value + } + +# ERROR Message values may not be used as selectors. + +# ERROR Term values may not be used as selectors. + +# ERROR Function references are invalid outside of call expressions, and this +# parses as a MessageReference which isn't a valid selector. + diff --git a/fluent-syntax/tests/fixtures/formatted/select_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/select_expressions.ftl new file mode 100644 index 00000000..8e1021b4 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/select_expressions.ftl @@ -0,0 +1,38 @@ +new-messages = + { BUILTIN() -> + [0] Zero + *[other] { "" }Other + } +valid-selector-term-attribute = + { -term.case -> + *[key] value + } + +# ERROR Term values are not valid selectors + +# ERROR CallExpressions on Terms are similar to TermReferences + +# ERROR Nested expressions are not valid selectors + +# ERROR Select expressions are not valid selectors + +empty-variant = + { $sel -> + *[key] { "" } + } +reduced-whitespace = + { FOO() -> + *[key] { "" } + } +nested-select = + { $sel -> + *[one] + { $sel -> + *[two] Value + } + } + +# ERROR Missing selector + +# ERROR Missing line end after variant list + diff --git a/fluent-syntax/tests/fixtures/formatted/select_indent.ftl b/fluent-syntax/tests/fixtures/formatted/select_indent.ftl new file mode 100644 index 00000000..9aa2a995 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/select_indent.ftl @@ -0,0 +1,65 @@ +select-1tbs-inline = + { $selector -> + *[key] Value + } +select-1tbs-newline = + { $selector -> + *[key] Value + } +select-1tbs-indent = + { $selector -> + *[key] Value + } +select-allman-inline = + { $selector -> + *[key] Value + [other] Other + } +select-allman-newline = + { $selector -> + *[key] Value + } +select-allman-indent = + { $selector -> + *[key] Value + } +select-gnu-inline = + { $selector -> + *[key] Value + } +select-gnu-newline = + { $selector -> + *[key] Value + } +select-gnu-indent = + { $selector -> + *[key] Value + } +select-no-indent = + { $selector -> + *[key] Value + [other] Other + } +select-no-indent-multiline = + { $selector -> + *[key] + Value + Continued + [other] + Other + Multiline + } + +# ERROR (Multiline text must be indented) + +select-flat = + { $selector -> + *[key] Value + [other] Other + } +# Each line ends with 5 spaces. +select-flat-with-trailing-spaces = + { $selector -> + *[key] Value + [other] Other + } diff --git a/fluent-syntax/tests/fixtures/formatted/sparse_entries.ftl b/fluent-syntax/tests/fixtures/formatted/sparse_entries.ftl new file mode 100644 index 00000000..dfa85945 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/sparse_entries.ftl @@ -0,0 +1,17 @@ +key01 = Value +key02 = + .attr = Attribute +key03 = + Value + Continued + + + Over multiple + Lines + .attr = Attribute +key05 = Value +key06 = + { 1 -> + [one] One + *[two] Two + } diff --git a/fluent-syntax/tests/fixtures/formatted/special_chars.ftl b/fluent-syntax/tests/fixtures/formatted/special_chars.ftl new file mode 100644 index 00000000..ab32df9d --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/special_chars.ftl @@ -0,0 +1,8 @@ +## OK + +bracket-inline = [Value] +dot-inline = .Value +star-inline = *Value + +## ERRORS + diff --git a/fluent-syntax/tests/fixtures/formatted/tab.ftl b/fluent-syntax/tests/fixtures/formatted/tab.ftl new file mode 100644 index 00000000..bbbd7332 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/tab.ftl @@ -0,0 +1,14 @@ +# OK (tab after = is part of the value) +key01 = Value 01 + +# Error (tab before =) + +# Error (tab is not a valid indent) + +# Partial Error (tab is not a valid indent) +key04 = This line is indented by 4 spaces, +# OK (value is a single tab) +key05 = +# OK (attribute value is two tabs) +key06 = + .attr = diff --git a/fluent-syntax/tests/fixtures/formatted/term_parameters.ftl b/fluent-syntax/tests/fixtures/formatted/term_parameters.ftl new file mode 100644 index 00000000..8ee2ed74 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/term_parameters.ftl @@ -0,0 +1,8 @@ +-term = + { $arg -> + *[key] Value + } +key01 = { -term } +key02 = { -term() } +key03 = { -term(arg: 1) } +key04 = { -term("positional", narg1: 1, narg2: 2) } diff --git a/fluent-syntax/tests/fixtures/formatted/terms.ftl b/fluent-syntax/tests/fixtures/formatted/terms.ftl new file mode 100644 index 00000000..37d68113 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/terms.ftl @@ -0,0 +1,20 @@ +-term01 = Value + .attr = Attribute +-term02 = { "" } + +# JUNK Missing value + +# JUNK Missing value +# < whitespace > + +# JUNK Missing value + +# JUNK Missing value +# < whitespace > + +# JUNK Missing = + +-term08 = Value + .attr = Attribute +-term09 = Value + .attr = Attribute diff --git a/fluent-syntax/tests/fixtures/formatted/variables.ftl b/fluent-syntax/tests/fixtures/formatted/variables.ftl new file mode 100644 index 00000000..25d58359 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/variables.ftl @@ -0,0 +1,14 @@ +key01 = { $var } +key02 = { $var } +key03 = { $var } +key04 = { $var } + +## Errors + + +# ERROR Missing variable identifier + +# ERROR Double $$ + +# ERROR Invalid first char of the identifier + diff --git a/fluent-syntax/tests/fixtures/formatted/variant_keys.ftl b/fluent-syntax/tests/fixtures/formatted/variant_keys.ftl new file mode 100644 index 00000000..d0313bcc --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/variant_keys.ftl @@ -0,0 +1,23 @@ +simple-identifier = + { $sel -> + *[key] value + } +identifier-surrounded-by-whitespace = + { $sel -> + *[key] value + } +int-number = + { $sel -> + *[1] value + } +float-number = + { $sel -> + *[3.14] value + } + +# ERROR + +# ERROR + +# ERROR + diff --git a/fluent-syntax/tests/fixtures/formatted/whitespace_in_value.ftl b/fluent-syntax/tests/fixtures/formatted/whitespace_in_value.ftl new file mode 100644 index 00000000..0cbcd371 --- /dev/null +++ b/fluent-syntax/tests/fixtures/formatted/whitespace_in_value.ftl @@ -0,0 +1,10 @@ +# Caution, lines 6 and 7 contain white-space-only lines +key = + first line + + + + + + + last line diff --git a/fluent-syntax/tests/fixtures/formatted/zero_length.ftl b/fluent-syntax/tests/fixtures/formatted/zero_length.ftl new file mode 100644 index 00000000..e69de29b diff --git a/fluent-syntax/tests/serializer_fixtures.rs b/fluent-syntax/tests/serializer_fixtures.rs index ab5b7225..c961ccef 100644 --- a/fluent-syntax/tests/serializer_fixtures.rs +++ b/fluent-syntax/tests/serializer_fixtures.rs @@ -1,4 +1,3 @@ -use fluent_syntax::ast::{Entry, Resource}; use glob::glob; use std::ffi::OsStr; use std::fs; @@ -22,19 +21,6 @@ fn is_ignored(path: &Path) -> bool { .unwrap_or_default() } -fn clone_without_junk<'a>(original: &Resource<&'a str>) -> Resource<&'a str> { - Resource { - body: original - .body - .iter() - .filter(|entry| !matches!(entry, Entry::Junk { .. })) - .cloned() - .collect(), - #[cfg(feature = "spans")] - span: original.span, - } -} - #[test] fn roundtrip_normalized_fixtures() { for entry in glob("./tests/fixtures/normalized/*.ftl").expect("Failed to read glob pattern") { @@ -59,15 +45,33 @@ fn roundtrip_unnormalized_fixtures() { let content = fs::read_to_string(&path).expect("Failed to read file"); let parsed = parse(content.as_str()).unwrap_or_else(|(res, _)| res); - let parsed_without_junk = clone_without_junk(&parsed); + let reserialized = serialize_with_options(&parsed, Options { with_junk: true }); let reserialized_without_junk = serialize_with_options(&parsed, Options { with_junk: false }); + + let formatted_path = path.parent().unwrap().join("formatted"); + + let formatted_content = fs::read_to_string( + formatted_path + .join("junked") + .join(path.file_name().unwrap()), + ) + .unwrap(); + assert_eq!(formatted_content, reserialized); + let formatted = parse(formatted_content.as_str()).unwrap_or_else(|(res, _)| res); + + let formatted_content_without_junk = + fs::read_to_string(formatted_path.join(path.file_name().unwrap())).unwrap(); + assert_eq!(formatted_content_without_junk, reserialized_without_junk); + let formatted_without_junk = + parse(formatted_content_without_junk.as_str()).unwrap_or_else(|(res, _)| res); + let reparsed = parse(reserialized.as_str()).unwrap_or_else(|(res, _)| res); let reparsed_without_junk = parse(reserialized_without_junk.as_str()).unwrap_or_else(|(res, _)| res); - assert_eq!(reparsed_without_junk, parsed_without_junk); - assert_eq!(reparsed, parsed); + assert_eq!(formatted_without_junk, reparsed_without_junk); + assert_eq!(formatted, reparsed); } } From 1d41394660d848cb3aea8a0b2a24e7b6fcd9f63b Mon Sep 17 00:00:00 2001 From: Ertanic Date: Sun, 9 Mar 2025 07:38:48 +0300 Subject: [PATCH 04/11] refactor(fluent-syntax): Make `Span` a wrapper around `std::ops::Range` --- fluent-syntax/src/ast/mod.rs | 21 +++++++++------------ fluent-syntax/src/parser/comment.rs | 2 +- fluent-syntax/src/parser/core.rs | 16 ++++++++-------- fluent-syntax/src/parser/expression.rs | 26 +++++++++++++------------- fluent-syntax/src/parser/pattern.rs | 6 +++--- fluent-syntax/src/parser/runtime.rs | 6 +++--- 6 files changed, 37 insertions(+), 40 deletions(-) diff --git a/fluent-syntax/src/ast/mod.rs b/fluent-syntax/src/ast/mod.rs index 365eca5d..ce664da5 100644 --- a/fluent-syntax/src/ast/mod.rs +++ b/fluent-syntax/src/ast/mod.rs @@ -88,6 +88,7 @@ mod helper; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +use std::ops::Deref; #[cfg(feature = "spans")] use std::ops::Range; @@ -1426,7 +1427,7 @@ pub enum InlineExpression { #[cfg(feature = "spans")] impl InlineExpression { - pub fn get_span(&self) -> Span { + pub fn get_span(&self) -> &Span { match self { InlineExpression::StringLiteral { span, .. } | InlineExpression::TermReference { span, .. } @@ -1434,7 +1435,7 @@ impl InlineExpression { | InlineExpression::Placeable { span, .. } | InlineExpression::NumberLiteral { span, .. } | InlineExpression::FunctionReference { span, .. } - | InlineExpression::MessageReference { span, .. } => *span, + | InlineExpression::MessageReference { span, .. } => span, } } } @@ -1560,17 +1561,13 @@ pub enum Expression { #[cfg(feature = "spans")] #[derive(Clone, Debug, Default, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct Span { - pub start: usize, - pub end: usize, -} +pub struct Span(pub Range); #[cfg(feature = "spans")] -impl Span { - pub fn new(range: Range) -> Self { - Self { - start: range.start, - end: range.end, - } +impl Deref for Span { + type Target = Range; + + fn deref(&self) -> &Self::Target { + &self.0 } } diff --git a/fluent-syntax/src/parser/comment.rs b/fluent-syntax/src/parser/comment.rs index 9fad6d2c..081edb66 100644 --- a/fluent-syntax/src/parser/comment.rs +++ b/fluent-syntax/src/parser/comment.rs @@ -54,7 +54,7 @@ where ast::Comment { content, #[cfg(feature = "spans")] - span: ast::Span::new(start_pos..self.ptr), + span: ast::Span(start_pos..self.ptr), }, level, )) diff --git a/fluent-syntax/src/parser/core.rs b/fluent-syntax/src/parser/core.rs index 08ccd5dd..87333355 100644 --- a/fluent-syntax/src/parser/core.rs +++ b/fluent-syntax/src/parser/core.rs @@ -70,7 +70,7 @@ where body.push(ast::Entry::Junk { content, #[cfg(feature = "spans")] - span: ast::Span::new(entry_start..self.ptr), + span: ast::Span(entry_start..self.ptr), }); } } @@ -84,14 +84,14 @@ where Ok(ast::Resource { body, #[cfg(feature = "spans")] - span: ast::Span::new(0..self.length), + span: ast::Span(0..self.length), }) } else { Err(( ast::Resource { body, #[cfg(feature = "spans")] - span: ast::Span::new(0..self.length), + span: ast::Span(0..self.length), }, errors, )) @@ -139,7 +139,7 @@ where attributes, comment: None, #[cfg(feature = "spans")] - span: ast::Span::new(entry_start..self.ptr), + span: ast::Span(entry_start..self.ptr), }) } @@ -163,7 +163,7 @@ where attributes, comment: None, #[cfg(feature = "spans")] - span: ast::Span::new(entry_start..self.ptr), + span: ast::Span(entry_start..self.ptr), }) } else { error!( @@ -207,7 +207,7 @@ where id, value: pattern, #[cfg(feature = "spans")] - span: ast::Span::new(self.ptr - 1..self.ptr), + span: ast::Span(self.ptr - 1..self.ptr), }), None => error!(ErrorKind::MissingValue, self.ptr), } @@ -229,7 +229,7 @@ where ast::Identifier { name, #[cfg(feature = "spans")] - span: ast::Span::new(start..self.ptr), + span: ast::Span(start..self.ptr), } } @@ -316,7 +316,7 @@ where value, default, #[cfg(feature = "spans")] - span: ast::Span::new((if default { start - 1 } else { start })..self.ptr), + span: ast::Span((if default { start - 1 } else { start })..self.ptr), }); self.skip_blank(); } else { diff --git a/fluent-syntax/src/parser/expression.rs b/fluent-syntax/src/parser/expression.rs index 014228e0..db72351d 100644 --- a/fluent-syntax/src/parser/expression.rs +++ b/fluent-syntax/src/parser/expression.rs @@ -23,7 +23,7 @@ where return Ok(ast::Expression::Inline( exp, #[cfg(feature = "spans")] - ast::Span::new(start_span..self.ptr), + ast::Span(start_span..self.ptr), )); } @@ -68,7 +68,7 @@ where selector: exp, variants, #[cfg(feature = "spans")] - span: ast::Span::new(start_span..self.ptr), + span: ast::Span(start_span..self.ptr), }) } @@ -112,7 +112,7 @@ where Ok(ast::InlineExpression::StringLiteral { value: slice, #[cfg(feature = "spans")] - span: ast::Span::new(start..self.ptr), + span: ast::Span(start..self.ptr), }) } Some(b) if b.is_ascii_digit() => { @@ -120,7 +120,7 @@ where Ok(ast::InlineExpression::NumberLiteral { value: num, #[cfg(feature = "spans")] - span: ast::Span::new(start..self.ptr), + span: ast::Span(start..self.ptr), }) } Some(b'-') if !only_literal => { @@ -135,7 +135,7 @@ where attribute, arguments, #[cfg(feature = "spans")] - span: ast::Span::new(start..self.ptr), + span: ast::Span(start..self.ptr), }) } else { self.ptr -= 1; @@ -143,7 +143,7 @@ where Ok(ast::InlineExpression::NumberLiteral { value: num, #[cfg(feature = "spans")] - span: ast::Span::new(start..self.ptr), + span: ast::Span(start..self.ptr), }) } } @@ -153,7 +153,7 @@ where Ok(ast::InlineExpression::VariableReference { id, #[cfg(feature = "spans")] - span: ast::Span::new(start..self.ptr), + span: ast::Span(start..self.ptr), }) } Some(b) if b.is_ascii_alphabetic() => { @@ -169,7 +169,7 @@ where id, arguments, #[cfg(feature = "spans")] - span: ast::Span::new(start..self.ptr), + span: ast::Span(start..self.ptr), }) } else { let attribute = self.get_attribute_accessor()?; @@ -177,7 +177,7 @@ where id, attribute, #[cfg(feature = "spans")] - span: ast::Span::new(start..self.ptr), + span: ast::Span(start..self.ptr), }) } } @@ -187,7 +187,7 @@ where Ok(ast::InlineExpression::Placeable { expression: Box::new(exp), #[cfg(feature = "spans")] - span: ast::Span::new(start..self.ptr), + span: ast::Span(start..self.ptr), }) } _ if only_literal => error!(ErrorKind::ExpectedLiteral, self.ptr), @@ -239,11 +239,11 @@ where name: ast::Identifier { name: id.name.clone(), #[cfg(feature = "spans")] - span: id.span, + span: id.span.clone(), }, value: val, #[cfg(feature = "spans")] - span: ast::Span::new(id.span.start..self.ptr), + span: ast::Span(id.span.start..self.ptr), }); } else { if !argument_names.is_empty() { @@ -269,7 +269,7 @@ where positional, named, #[cfg(feature = "spans")] - span: ast::Span::new(start..self.ptr), + span: ast::Span(start..self.ptr), })) } } diff --git a/fluent-syntax/src/parser/pattern.rs b/fluent-syntax/src/parser/pattern.rs index d0a6330d..6c822646 100644 --- a/fluent-syntax/src/parser/pattern.rs +++ b/fluent-syntax/src/parser/pattern.rs @@ -147,7 +147,7 @@ where PatternElementPlaceholders::Placeable(expression, range) => { ast::PatternElement::Placeable { expression, - span: ast::Span::new(range), + span: ast::Span(range), } } #[cfg(not(feature = "spans"))] @@ -170,7 +170,7 @@ where ast::PatternElement::TextElement { value, #[cfg(feature = "spans")] - span: ast::Span::new(start..end), + span: ast::Span(start..end), } } }) @@ -178,7 +178,7 @@ where return Ok(Some(ast::Pattern { elements, #[cfg(feature = "spans")] - span: ast::Span::new(start_pos..self.ptr), + span: ast::Span(start_pos..self.ptr), })); } diff --git a/fluent-syntax/src/parser/runtime.rs b/fluent-syntax/src/parser/runtime.rs index 4c7ce18d..a95383dc 100644 --- a/fluent-syntax/src/parser/runtime.rs +++ b/fluent-syntax/src/parser/runtime.rs @@ -37,7 +37,7 @@ where body.push(ast::Entry::Junk { content, #[cfg(feature = "spans")] - span: ast::Span::new(entry_start..self.ptr), + span: ast::Span(entry_start..self.ptr), }); } } @@ -48,14 +48,14 @@ where Ok(ast::Resource { body, #[cfg(feature = "spans")] - span: ast::Span::new(0..self.length), + span: ast::Span(0..self.length), }) } else { Err(( ast::Resource { body, #[cfg(feature = "spans")] - span: ast::Span::new(0..self.length), + span: ast::Span(0..self.length), }, errors, )) From 7346a0fb15c34dde2d0ff95253329281b53d41ba Mon Sep 17 00:00:00 2001 From: Ertanic Date: Wed, 21 May 2025 10:52:25 +0300 Subject: [PATCH 05/11] test(fluent-syntax): Update test handling to support spans --- fluent-syntax/Cargo.toml | 3 +++ fluent-syntax/src/ast/mod.rs | 3 +-- fluent-syntax/src/parser/core.rs | 4 +++- fluent-syntax/src/serializer.rs | 1 + fluent-syntax/tests/helper/mod.rs | 38 +++++++++++++++++++++++++------ 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/fluent-syntax/Cargo.toml b/fluent-syntax/Cargo.toml index e9efcd54..f274a2be 100644 --- a/fluent-syntax/Cargo.toml +++ b/fluent-syntax/Cargo.toml @@ -64,3 +64,6 @@ required-features = ["json"] name = "parser_fixtures" path = "tests/parser_fixtures.rs" required-features = ["json"] + +[lib] +doctest = false diff --git a/fluent-syntax/src/ast/mod.rs b/fluent-syntax/src/ast/mod.rs index ce664da5..e9663749 100644 --- a/fluent-syntax/src/ast/mod.rs +++ b/fluent-syntax/src/ast/mod.rs @@ -88,9 +88,8 @@ mod helper; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use std::ops::Deref; #[cfg(feature = "spans")] -use std::ops::Range; +use std::ops::{Deref, Range}; /// Root node of a Fluent Translation List. /// diff --git a/fluent-syntax/src/parser/core.rs b/fluent-syntax/src/parser/core.rs index 87333355..bff1b82f 100644 --- a/fluent-syntax/src/parser/core.rs +++ b/fluent-syntax/src/parser/core.rs @@ -3,7 +3,9 @@ use super::{ errors::{ErrorKind, ParserError}, slice::Slice, }; -use crate::ast::{self, Span}; +use crate::ast; +#[cfg(feature = "spans")] +use crate::ast::Span; pub type Result = std::result::Result; diff --git a/fluent-syntax/src/serializer.rs b/fluent-syntax/src/serializer.rs index a6dba321..8291910a 100644 --- a/fluent-syntax/src/serializer.rs +++ b/fluent-syntax/src/serializer.rs @@ -580,6 +580,7 @@ mod test { let one_variant = Variant { key: VariantKey::Identifier { name: "one", + #[cfg(feature = "spans")] span: Span::default(), }, value: Pattern { diff --git a/fluent-syntax/tests/helper/mod.rs b/fluent-syntax/tests/helper/mod.rs index fe484ca5..cb981e9a 100644 --- a/fluent-syntax/tests/helper/mod.rs +++ b/fluent-syntax/tests/helper/mod.rs @@ -13,7 +13,7 @@ fn adapt_pattern(pattern: &mut ast::Pattern, crlf: bool) { let mut elements = vec![]; for element in &pattern.elements { match element { - ast::PatternElement::TextElement { value } => { + ast::PatternElement::TextElement { value, .. } => { let mut start = 0; let len = value.len(); for (i, b) in value.as_bytes().iter().enumerate() { @@ -22,29 +22,53 @@ fn adapt_pattern(pattern: &mut ast::Pattern, crlf: bool) { if i > start { let chunk = &value.as_bytes()[start..=i - 1]; let value = String::from_utf8_lossy(chunk).to_string(); - elements.push(ast::PatternElement::TextElement { value }); + elements.push(ast::PatternElement::TextElement { + value, + #[cfg(feature = "spans")] + span: ast::Span(start..i), + }); } + elements.push(ast::PatternElement::TextElement { value: "\n".to_string(), + #[cfg(feature = "spans")] + span: ast::Span(i..i + 1), }); } else { let chunk = &value.as_bytes()[start..=i]; let value = String::from_utf8_lossy(chunk).to_string(); - elements.push(ast::PatternElement::TextElement { value }); + elements.push(ast::PatternElement::TextElement { + value, + #[cfg(feature = "spans")] + span: ast::Span(start..i + 1), + }); } start = i + 1; } } + if start < len { let chunk = &value.as_bytes()[start..len]; let value = String::from_utf8_lossy(chunk).to_string(); - elements.push(ast::PatternElement::TextElement { value }); + elements.push(ast::PatternElement::TextElement { + value, + #[cfg(feature = "spans")] + span: ast::Span(start..len), + }); } } - ast::PatternElement::Placeable { expression } => { + ast::PatternElement::Placeable { + expression, + #[cfg(feature = "spans")] + span, + } => { let mut expression = expression.clone(); adapt_expression(&mut expression, crlf); - elements.push(ast::PatternElement::Placeable { expression }); + elements.push(ast::PatternElement::Placeable { + expression, + #[cfg(feature = "spans")] + span: span.clone(), + }); } } } @@ -58,7 +82,7 @@ fn adapt_expression(expression: &mut ast::Expression, crlf: bool) { adapt_pattern(&mut variant.value, crlf); } } - ast::Expression::Inline(_) => {} + ast::Expression::Inline(..) => {} } } From 61eadefebebe9c078e5d0d5dda090d4460311135 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 21 May 2025 16:33:11 +0300 Subject: [PATCH 06/11] docs: Add changelog entries covering spans PR --- fluent-bundle/CHANGELOG.md | 1 + fluent-syntax/CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/fluent-bundle/CHANGELOG.md b/fluent-bundle/CHANGELOG.md index 4e25f1cc..f99ad317 100644 --- a/fluent-bundle/CHANGELOG.md +++ b/fluent-bundle/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased - Implement NUMBER builtin + - Adapt for new optional source positions span feature in syntax parser - Improve examples - Refactor to remove unnecessary named lifetimes - Cleanup docs diff --git a/fluent-syntax/CHANGELOG.md b/fluent-syntax/CHANGELOG.md index 435fb448..3cb04fca 100644 --- a/fluent-syntax/CHANGELOG.md +++ b/fluent-syntax/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased + - Add `spans` feature to track source positions in the AST - Add module `serializer` - De-ambiguate dependencies vs. features - Cleanup docs From f73665a363236cf7e23fb4578ecfd5714d0207b8 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 22 May 2025 14:14:21 +0300 Subject: [PATCH 07/11] Revert "refactor(fluent-syntax): Use pre-formatted messages for `roundtrip_unnormalized_fixtures()`" This reverts commit 0756bd1dfbe6b7b7ca94241a8dcf83c6aad3d10d. --- .gitattributes | 4 +- .../tests/fixtures/formatted/any_char.ftl | 6 -- .../tests/fixtures/formatted/astral.ftl | 14 ---- .../fixtures/formatted/call_expressions.ftl | 56 --------------- .../fixtures/formatted/callee_expressions.ftl | 36 ---------- .../tests/fixtures/formatted/comments.ftl | 22 ------ fluent-syntax/tests/fixtures/formatted/cr.ftl | 2 - .../tests/fixtures/formatted/eof_comment.ftl | 5 -- .../tests/fixtures/formatted/eof_empty.ftl | 0 .../tests/fixtures/formatted/eof_id.ftl | 2 - .../fixtures/formatted/eof_id_equals.ftl | 2 - .../tests/fixtures/formatted/eof_junk.ftl | 2 - .../tests/fixtures/formatted/eof_value.ftl | 3 - .../fixtures/formatted/escaped_characters.ftl | 38 ---------- .../tests/fixtures/formatted/junk.ftl | 16 ----- .../fixtures/formatted/junked/any_char.ftl | 6 -- .../fixtures/formatted/junked/astral.ftl | 21 ------ .../formatted/junked/call_expressions.ftl | 71 ------------------- .../formatted/junked/callee_expressions.ftl | 58 --------------- .../fixtures/formatted/junked/comments.ftl | 25 ------- .../tests/fixtures/formatted/junked/cr.ftl | 2 - .../fixtures/formatted/junked/eof_comment.ftl | 5 -- .../fixtures/formatted/junked/eof_empty.ftl | 0 .../fixtures/formatted/junked/eof_id.ftl | 3 - .../formatted/junked/eof_id_equals.ftl | 3 - .../fixtures/formatted/junked/eof_junk.ftl | 3 - .../fixtures/formatted/junked/eof_value.ftl | 3 - .../formatted/junked/escaped_characters.ftl | 46 ------------ .../tests/fixtures/formatted/junked/junk.ftl | 28 -------- .../formatted/junked/leading_dots.ftl | 70 ------------------ .../formatted/junked/literal_expressions.ftl | 3 - .../formatted/junked/member_expressions.ftl | 23 ------ .../fixtures/formatted/junked/messages.ftl | 45 ------------ .../formatted/junked/mixed_entries.ftl | 24 ------- .../fixtures/formatted/junked/numbers.ftl | 32 --------- .../fixtures/formatted/junked/obsolete.ftl | 29 -------- .../fixtures/formatted/junked/placeables.ftl | 19 ----- .../junked/reference_expressions.ftl | 32 --------- .../formatted/junked/select_expressions.ftl | 68 ------------------ .../formatted/junked/select_indent.ftl | 70 ------------------ .../formatted/junked/sparse_entries.ftl | 17 ----- .../formatted/junked/special_chars.ftl | 14 ---- .../tests/fixtures/formatted/junked/tab.ftl | 21 ------ .../formatted/junked/term_parameters.ftl | 8 --- .../tests/fixtures/formatted/junked/terms.ftl | 32 --------- .../fixtures/formatted/junked/variables.ftl | 17 ----- .../formatted/junked/variant_keys.ftl | 37 ---------- .../formatted/junked/whitespace_in_value.ftl | 10 --- .../fixtures/formatted/junked/zero_length.ftl | 0 .../tests/fixtures/formatted/leading_dots.ftl | 46 ------------ .../formatted/literal_expressions.ftl | 3 - .../fixtures/formatted/member_expressions.ftl | 17 ----- .../tests/fixtures/formatted/messages.ftl | 36 ---------- .../fixtures/formatted/mixed_entries.ftl | 19 ----- .../tests/fixtures/formatted/numbers.ftl | 25 ------- .../tests/fixtures/formatted/obsolete.ftl | 9 --- .../tests/fixtures/formatted/placeables.ftl | 12 ---- .../formatted/reference_expressions.ftl | 23 ------ .../fixtures/formatted/select_expressions.ftl | 38 ---------- .../fixtures/formatted/select_indent.ftl | 65 ----------------- .../fixtures/formatted/sparse_entries.ftl | 17 ----- .../fixtures/formatted/special_chars.ftl | 8 --- .../tests/fixtures/formatted/tab.ftl | 14 ---- .../fixtures/formatted/term_parameters.ftl | 8 --- .../tests/fixtures/formatted/terms.ftl | 20 ------ .../tests/fixtures/formatted/variables.ftl | 14 ---- .../tests/fixtures/formatted/variant_keys.ftl | 23 ------ .../formatted/whitespace_in_value.ftl | 10 --- .../tests/fixtures/formatted/zero_length.ftl | 0 fluent-syntax/tests/serializer_fixtures.rs | 38 +++++----- 70 files changed, 18 insertions(+), 1480 deletions(-) delete mode 100644 fluent-syntax/tests/fixtures/formatted/any_char.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/astral.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/call_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/callee_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/comments.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/cr.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/eof_comment.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/eof_empty.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/eof_id.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/eof_id_equals.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/eof_junk.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/eof_value.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/escaped_characters.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junk.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/any_char.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/astral.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/call_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/callee_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/comments.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/cr.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_comment.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_empty.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_id.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_id_equals.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_junk.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/eof_value.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/escaped_characters.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/junk.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/leading_dots.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/literal_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/member_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/messages.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/mixed_entries.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/numbers.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/obsolete.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/placeables.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/reference_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/select_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/select_indent.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/sparse_entries.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/special_chars.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/tab.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/term_parameters.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/terms.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/variables.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/variant_keys.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/whitespace_in_value.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/junked/zero_length.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/leading_dots.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/literal_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/member_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/messages.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/mixed_entries.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/numbers.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/obsolete.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/placeables.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/reference_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/select_expressions.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/select_indent.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/sparse_entries.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/special_chars.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/tab.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/term_parameters.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/terms.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/variables.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/variant_keys.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/whitespace_in_value.ftl delete mode 100644 fluent-syntax/tests/fixtures/formatted/zero_length.ftl diff --git a/.gitattributes b/.gitattributes index 00ae28f9..dcefbe38 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,4 @@ *.ftl eol=lf -fluent-syntax/tests/fixtures/cr.ftl eol=cr fluent-syntax/tests/fixtures/crlf.ftl eol=crlf -fluent-syntax/tests/fixtures/formatted/cr.ftl eol=cr -fluent-syntax/tests/fixtures/formatted/junked/cr.ftl eol=cr +fluent-syntax/tests/fixtures/cr.ftl eol=cr diff --git a/fluent-syntax/tests/fixtures/formatted/any_char.ftl b/fluent-syntax/tests/fixtures/formatted/any_char.ftl deleted file mode 100644 index 76a1839b..00000000 --- a/fluent-syntax/tests/fixtures/formatted/any_char.ftl +++ /dev/null @@ -1,6 +0,0 @@ -# ↓ BEL, U+0007 -control0 = abcdef -# ↓ DEL, U+007F -delete = abcdef -# ↓ BPM, U+0082 -control1 = abc‚def diff --git a/fluent-syntax/tests/fixtures/formatted/astral.ftl b/fluent-syntax/tests/fixtures/formatted/astral.ftl deleted file mode 100644 index f650be0f..00000000 --- a/fluent-syntax/tests/fixtures/formatted/astral.ftl +++ /dev/null @@ -1,14 +0,0 @@ -face-with-tears-of-joy = 😂 -tetragram-for-centre = 𝌆 -surrogates-in-text = \uD83D\uDE02 -surrogates-in-string = { "\uD83D\uDE02" } -surrogates-in-adjacent-strings = { "\uD83D" }{ "\uDE02" } -emoji-in-text = A face 😂 with tears of joy. -emoji-in-string = { "A face 😂 with tears of joy." } - -# ERROR Invalid identifier - -# ERROR Invalid expression - -# ERROR Invalid variant key - diff --git a/fluent-syntax/tests/fixtures/formatted/call_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/call_expressions.ftl deleted file mode 100644 index ffef8dca..00000000 --- a/fluent-syntax/tests/fixtures/formatted/call_expressions.ftl +++ /dev/null @@ -1,56 +0,0 @@ -## Function names - -valid-func-name-01 = { FUN1() } -valid-func-name-02 = { FUN_FUN() } -valid-func-name-03 = { FUN-FUN() } - -# JUNK 0 is not a valid Identifier start - -# JUNK Function names may not be lowercase - -# JUNK Function names may not contain lowercase character - -# JUNK ? is not a valid Identifier character - -## Arguments - -positional-args = { FUN(1, "a", msg) } -named-args = { FUN(x: 1, y: "Y") } -dense-named-args = { FUN(x: 1, y: "Y") } -mixed-args = { FUN(1, "a", msg, x: 1, y: "Y") } - -# ERROR Positional arg must not follow keyword args - -# ERROR Named arguments must be unique - -## Whitespace around arguments - -sparse-inline-call = { FUN("a", msg, x: 1) } -empty-inline-call = { FUN() } -multiline-call = { FUN("a", msg, x: 1) } -sparse-multiline-call = { FUN("a", msg, x: 1) } -empty-multiline-call = { FUN() } -unindented-arg-number = { FUN(1) } -unindented-arg-string = { FUN("a") } -unindented-arg-msg-ref = { FUN(msg) } -unindented-arg-term-ref = { FUN(-msg) } -unindented-arg-var-ref = { FUN($var) } -unindented-arg-call = { FUN(OTHER()) } -unindented-named-arg = { FUN(x: 1) } -unindented-closing-paren = { FUN(x) } - -## Optional trailing comma - -one-argument = { FUN(1) } -many-arguments = { FUN(1, 2, 3) } -inline-sparse-args = { FUN(1, 2, 3) } -mulitline-args = { FUN(1, 2) } -mulitline-sparse-args = { FUN(1, 2) } - -## Syntax errors for trailing comma - -## Whitespace in named arguments - -sparse-named-arg = { FUN(x: 1, y: 2, z: 3) } -unindented-colon = { FUN(x: 1) } -unindented-value = { FUN(x: 1) } diff --git a/fluent-syntax/tests/fixtures/formatted/callee_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/callee_expressions.ftl deleted file mode 100644 index edc68ab5..00000000 --- a/fluent-syntax/tests/fixtures/formatted/callee_expressions.ftl +++ /dev/null @@ -1,36 +0,0 @@ -## Callees in placeables. - -function-callee-placeable = { FUNCTION() } -term-callee-placeable = { -term() } - -# ERROR Messages cannot be parameterized. - -# ERROR Equivalent to a MessageReference callee. - -# ERROR Message attributes cannot be parameterized. - -# ERROR Term attributes may not be used in Placeables. - -# ERROR Variables cannot be parameterized. - -## Callees in selectors. - -function-callee-selector = - { FUNCTION() -> - *[key] Value - } -term-attr-callee-selector = - { -term.attr() -> - *[key] Value - } - -# ERROR Messages cannot be parameterized. - -# ERROR Equivalent to a MessageReference callee. - -# ERROR Message attributes cannot be parameterized. - -# ERROR Term values may not be used as selectors. - -# ERROR Variables cannot be parameterized. - diff --git a/fluent-syntax/tests/fixtures/formatted/comments.ftl b/fluent-syntax/tests/fixtures/formatted/comments.ftl deleted file mode 100644 index 45754cd9..00000000 --- a/fluent-syntax/tests/fixtures/formatted/comments.ftl +++ /dev/null @@ -1,22 +0,0 @@ -# Standalone Comment - -# Message Comment -foo = Foo -# Term Comment -# with a blank last line. -# --term = Term - -# Another standalone -# -# with indent - - -## Group Comment - - -### Resource Comment - - -# Errors - diff --git a/fluent-syntax/tests/fixtures/formatted/cr.ftl b/fluent-syntax/tests/fixtures/formatted/cr.ftl deleted file mode 100644 index ace98efb..00000000 --- a/fluent-syntax/tests/fixtures/formatted/cr.ftl +++ /dev/null @@ -1,2 +0,0 @@ -### This entire file uses CR as EOL. err01 = Value 01 err02 = Value 02 err03 = Value 03 Continued .title = Title err04 = { "str err05 = { $sel -> } - diff --git a/fluent-syntax/tests/fixtures/formatted/eof_comment.ftl b/fluent-syntax/tests/fixtures/formatted/eof_comment.ftl deleted file mode 100644 index d262c3b3..00000000 --- a/fluent-syntax/tests/fixtures/formatted/eof_comment.ftl +++ /dev/null @@ -1,5 +0,0 @@ -### NOTE: Disable final newline insertion when editing this file. - - -# No EOL - diff --git a/fluent-syntax/tests/fixtures/formatted/eof_empty.ftl b/fluent-syntax/tests/fixtures/formatted/eof_empty.ftl deleted file mode 100644 index e69de29b..00000000 diff --git a/fluent-syntax/tests/fixtures/formatted/eof_id.ftl b/fluent-syntax/tests/fixtures/formatted/eof_id.ftl deleted file mode 100644 index c938b0bc..00000000 --- a/fluent-syntax/tests/fixtures/formatted/eof_id.ftl +++ /dev/null @@ -1,2 +0,0 @@ -### NOTE: Disable final newline insertion when editing this file. - diff --git a/fluent-syntax/tests/fixtures/formatted/eof_id_equals.ftl b/fluent-syntax/tests/fixtures/formatted/eof_id_equals.ftl deleted file mode 100644 index c938b0bc..00000000 --- a/fluent-syntax/tests/fixtures/formatted/eof_id_equals.ftl +++ /dev/null @@ -1,2 +0,0 @@ -### NOTE: Disable final newline insertion when editing this file. - diff --git a/fluent-syntax/tests/fixtures/formatted/eof_junk.ftl b/fluent-syntax/tests/fixtures/formatted/eof_junk.ftl deleted file mode 100644 index c938b0bc..00000000 --- a/fluent-syntax/tests/fixtures/formatted/eof_junk.ftl +++ /dev/null @@ -1,2 +0,0 @@ -### NOTE: Disable final newline insertion when editing this file. - diff --git a/fluent-syntax/tests/fixtures/formatted/eof_value.ftl b/fluent-syntax/tests/fixtures/formatted/eof_value.ftl deleted file mode 100644 index 23ee1b60..00000000 --- a/fluent-syntax/tests/fixtures/formatted/eof_value.ftl +++ /dev/null @@ -1,3 +0,0 @@ -### NOTE: Disable final newline insertion when editing this file. - -no-eol = No EOL diff --git a/fluent-syntax/tests/fixtures/formatted/escaped_characters.ftl b/fluent-syntax/tests/fixtures/formatted/escaped_characters.ftl deleted file mode 100644 index 29c56f50..00000000 --- a/fluent-syntax/tests/fixtures/formatted/escaped_characters.ftl +++ /dev/null @@ -1,38 +0,0 @@ -## Literal text - -text-backslash-one = Value with \ a backslash -text-backslash-two = Value with \\ two backslashes -text-backslash-brace = Value with \{ placeable } -text-backslash-u = \u0041 -text-backslash-backslash-u = \\u0041 - -## String literals - -quote-in-string = { "\"" } -backslash-in-string = { "\\" } - -# ERROR Mismatched quote - -# ERROR Unknown escape - -# ERROR Multiline literal - -## Unicode escapes - -string-unicode-4digits = { "\u0041" } -escape-unicode-4digits = { "\\u0041" } -string-unicode-6digits = { "\U01F602" } -escape-unicode-6digits = { "\\U01F602" } -# OK The trailing "00" is part of the literal value. -string-too-many-4digits = { "\u004100" } -# OK The trailing "00" is part of the literal value. -string-too-many-6digits = { "\U01F60200" } - -# ERROR Too few hex digits after \u. - -# ERROR Too few hex digits after \U. - -## Literal braces - -brace-open = An opening { "{" } brace. -brace-close = A closing { "}" } brace. diff --git a/fluent-syntax/tests/fixtures/formatted/junk.ftl b/fluent-syntax/tests/fixtures/formatted/junk.ftl deleted file mode 100644 index d0ff0158..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junk.ftl +++ /dev/null @@ -1,16 +0,0 @@ -## Two adjacent Junks. - -# A single Junk. - -# A single Junk. - -# The COMMENT ends this junk. - -# COMMENT - - -# The COMMENT ends this junk. -# The closing brace is a separate Junk. - -# COMMENT - diff --git a/fluent-syntax/tests/fixtures/formatted/junked/any_char.ftl b/fluent-syntax/tests/fixtures/formatted/junked/any_char.ftl deleted file mode 100644 index 76a1839b..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/any_char.ftl +++ /dev/null @@ -1,6 +0,0 @@ -# ↓ BEL, U+0007 -control0 = abcdef -# ↓ DEL, U+007F -delete = abcdef -# ↓ BPM, U+0082 -control1 = abc‚def diff --git a/fluent-syntax/tests/fixtures/formatted/junked/astral.ftl b/fluent-syntax/tests/fixtures/formatted/junked/astral.ftl deleted file mode 100644 index f29fef0a..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/astral.ftl +++ /dev/null @@ -1,21 +0,0 @@ -face-with-tears-of-joy = 😂 -tetragram-for-centre = 𝌆 -surrogates-in-text = \uD83D\uDE02 -surrogates-in-string = { "\uD83D\uDE02" } -surrogates-in-adjacent-strings = { "\uD83D" }{ "\uDE02" } -emoji-in-text = A face 😂 with tears of joy. -emoji-in-string = { "A face 😂 with tears of joy." } - -# ERROR Invalid identifier - -err-😂 = Value - -# ERROR Invalid expression - -err-invalid-expression = { 😂 } - -# ERROR Invalid variant key - -err-invalid-variant-key = { $sel -> - *[😂] Value -} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/call_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/call_expressions.ftl deleted file mode 100644 index 46a531fe..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/call_expressions.ftl +++ /dev/null @@ -1,71 +0,0 @@ -## Function names - -valid-func-name-01 = { FUN1() } -valid-func-name-02 = { FUN_FUN() } -valid-func-name-03 = { FUN-FUN() } - -# JUNK 0 is not a valid Identifier start - -invalid-func-name-01 = {0FUN()} -# JUNK Function names may not be lowercase - -invalid-func-name-02 = {fun()} -# JUNK Function names may not contain lowercase character - -invalid-func-name-03 = {Fun()} -# JUNK ? is not a valid Identifier character - -invalid-func-name-04 = {FUN?()} - -## Arguments - -positional-args = { FUN(1, "a", msg) } -named-args = { FUN(x: 1, y: "Y") } -dense-named-args = { FUN(x: 1, y: "Y") } -mixed-args = { FUN(1, "a", msg, x: 1, y: "Y") } - -# ERROR Positional arg must not follow keyword args - -shuffled-args = {FUN(1, x: 1, "a", y: "Y", msg)} - -# ERROR Named arguments must be unique - -duplicate-named-args = {FUN(x: 1, x: "X")} - - -## Whitespace around arguments - -sparse-inline-call = { FUN("a", msg, x: 1) } -empty-inline-call = { FUN() } -multiline-call = { FUN("a", msg, x: 1) } -sparse-multiline-call = { FUN("a", msg, x: 1) } -empty-multiline-call = { FUN() } -unindented-arg-number = { FUN(1) } -unindented-arg-string = { FUN("a") } -unindented-arg-msg-ref = { FUN(msg) } -unindented-arg-term-ref = { FUN(-msg) } -unindented-arg-var-ref = { FUN($var) } -unindented-arg-call = { FUN(OTHER()) } -unindented-named-arg = { FUN(x: 1) } -unindented-closing-paren = { FUN(x) } - -## Optional trailing comma - -one-argument = { FUN(1) } -many-arguments = { FUN(1, 2, 3) } -inline-sparse-args = { FUN(1, 2, 3) } -mulitline-args = { FUN(1, 2) } -mulitline-sparse-args = { FUN(1, 2) } - -## Syntax errors for trailing comma - -one-argument = {FUN(1,,)} -missing-arg = {FUN(,)} -missing-sparse-arg = {FUN( , )} - - -## Whitespace in named arguments - -sparse-named-arg = { FUN(x: 1, y: 2, z: 3) } -unindented-colon = { FUN(x: 1) } -unindented-value = { FUN(x: 1) } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/callee_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/callee_expressions.ftl deleted file mode 100644 index ca98eae7..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/callee_expressions.ftl +++ /dev/null @@ -1,58 +0,0 @@ -## Callees in placeables. - -function-callee-placeable = { FUNCTION() } -term-callee-placeable = { -term() } - -# ERROR Messages cannot be parameterized. - -message-callee-placeable = {message()} -# ERROR Equivalent to a MessageReference callee. - -mixed-case-callee-placeable = {Function()} -# ERROR Message attributes cannot be parameterized. - -message-attr-callee-placeable = {message.attr()} -# ERROR Term attributes may not be used in Placeables. - -term-attr-callee-placeable = {-term.attr()} -# ERROR Variables cannot be parameterized. - -variable-callee-placeable = {$variable()} - - -## Callees in selectors. - -function-callee-selector = - { FUNCTION() -> - *[key] Value - } -term-attr-callee-selector = - { -term.attr() -> - *[key] Value - } - -# ERROR Messages cannot be parameterized. - -message-callee-selector = {message() -> - *[key] Value -} -# ERROR Equivalent to a MessageReference callee. - -mixed-case-callee-selector = {Function() -> - *[key] Value -} -# ERROR Message attributes cannot be parameterized. - -message-attr-callee-selector = {message.attr() -> - *[key] Value -} -# ERROR Term values may not be used as selectors. - -term-callee-selector = {-term() -> - *[key] Value -} -# ERROR Variables cannot be parameterized. - -variable-callee-selector = {$variable() -> - *[key] Value -} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/comments.ftl b/fluent-syntax/tests/fixtures/formatted/junked/comments.ftl deleted file mode 100644 index be10bad2..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/comments.ftl +++ /dev/null @@ -1,25 +0,0 @@ -# Standalone Comment - -# Message Comment -foo = Foo -# Term Comment -# with a blank last line. -# --term = Term - -# Another standalone -# -# with indent - - -## Group Comment - - -### Resource Comment - - -# Errors - -#error -##error -###error diff --git a/fluent-syntax/tests/fixtures/formatted/junked/cr.ftl b/fluent-syntax/tests/fixtures/formatted/junked/cr.ftl deleted file mode 100644 index ace98efb..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/cr.ftl +++ /dev/null @@ -1,2 +0,0 @@ -### This entire file uses CR as EOL. err01 = Value 01 err02 = Value 02 err03 = Value 03 Continued .title = Title err04 = { "str err05 = { $sel -> } - diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_comment.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_comment.ftl deleted file mode 100644 index d262c3b3..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/eof_comment.ftl +++ /dev/null @@ -1,5 +0,0 @@ -### NOTE: Disable final newline insertion when editing this file. - - -# No EOL - diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_empty.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_empty.ftl deleted file mode 100644 index e69de29b..00000000 diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_id.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_id.ftl deleted file mode 100644 index 63fa86d6..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/eof_id.ftl +++ /dev/null @@ -1,3 +0,0 @@ -### NOTE: Disable final newline insertion when editing this file. - -message-id \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_id_equals.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_id_equals.ftl deleted file mode 100644 index 7d0d953a..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/eof_id_equals.ftl +++ /dev/null @@ -1,3 +0,0 @@ -### NOTE: Disable final newline insertion when editing this file. - -message-id = \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_junk.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_junk.ftl deleted file mode 100644 index dbafd3a3..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/eof_junk.ftl +++ /dev/null @@ -1,3 +0,0 @@ -### NOTE: Disable final newline insertion when editing this file. - -000 \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/formatted/junked/eof_value.ftl b/fluent-syntax/tests/fixtures/formatted/junked/eof_value.ftl deleted file mode 100644 index 23ee1b60..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/eof_value.ftl +++ /dev/null @@ -1,3 +0,0 @@ -### NOTE: Disable final newline insertion when editing this file. - -no-eol = No EOL diff --git a/fluent-syntax/tests/fixtures/formatted/junked/escaped_characters.ftl b/fluent-syntax/tests/fixtures/formatted/junked/escaped_characters.ftl deleted file mode 100644 index b6025b76..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/escaped_characters.ftl +++ /dev/null @@ -1,46 +0,0 @@ -## Literal text - -text-backslash-one = Value with \ a backslash -text-backslash-two = Value with \\ two backslashes -text-backslash-brace = Value with \{ placeable } -text-backslash-u = \u0041 -text-backslash-backslash-u = \\u0041 - -## String literals - -quote-in-string = { "\"" } -backslash-in-string = { "\\" } - -# ERROR Mismatched quote - -mismatched-quote = {"\\""} -# ERROR Unknown escape - -unknown-escape = {"\x"} -# ERROR Multiline literal - -invalid-multiline-literal = {" - "} - -## Unicode escapes - -string-unicode-4digits = { "\u0041" } -escape-unicode-4digits = { "\\u0041" } -string-unicode-6digits = { "\U01F602" } -escape-unicode-6digits = { "\\U01F602" } -# OK The trailing "00" is part of the literal value. -string-too-many-4digits = { "\u004100" } -# OK The trailing "00" is part of the literal value. -string-too-many-6digits = { "\U01F60200" } - -# ERROR Too few hex digits after \u. - -string-too-few-4digits = {"\u41"} -# ERROR Too few hex digits after \U. - -string-too-few-6digits = {"\U1F602"} - -## Literal braces - -brace-open = An opening { "{" } brace. -brace-close = A closing { "}" } brace. diff --git a/fluent-syntax/tests/fixtures/formatted/junked/junk.ftl b/fluent-syntax/tests/fixtures/formatted/junked/junk.ftl deleted file mode 100644 index 6085bb92..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/junk.ftl +++ /dev/null @@ -1,28 +0,0 @@ -## Two adjacent Junks. - -err01 = {1x} -err02 = {2x} - -# A single Junk. - -err03 = {1x -2 - -# A single Junk. - -ą=Invalid identifier -ć=Another one - -# The COMMENT ends this junk. - -err04 = { -# COMMENT - - -# The COMMENT ends this junk. -# The closing brace is a separate Junk. - -err04 = { -# COMMENT - -} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/leading_dots.ftl b/fluent-syntax/tests/fixtures/formatted/junked/leading_dots.ftl deleted file mode 100644 index e87e4097..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/leading_dots.ftl +++ /dev/null @@ -1,70 +0,0 @@ -key01 = .Value -key02 = …Value -key03 = { "." }Value -key04 = { "." }Value -key05 = - Value - { "." }Continued -key06 = .Value -{ "." }Continued -# MESSAGE (value = "Value", attributes = []) -# JUNK (attr .Continued" must have a value) -key07 = Value - .Continued - -# JUNK (attr .Value must have a value) - -key08 = - .Value - -# JUNK (attr .Value must have a value) - -key09 = - .Value - Continued - -key10 = - .Value = - which is an attribute - Continued -key11 = - { "." }Value = which looks like an attribute - Continued -key12 = - .accesskey = A -key13 = - .attribute = .Value -key14 = - .attribute = { "." }Value -key15 = - { 1 -> - [one] .Value - *[other] { "." }Value - } - -# JUNK (variant must have a value) - -key16 = - { 1 -> - *[one] - .Value - } - -# JUNK (unclosed placeable) - -key17 = - { 1 -> - *[one] Value - .Continued - } - -# JUNK (attr .Value must have a value) - -key18 = -.Value - -key19 = - .attribute = - Value - Continued -key20 = { "." }Value diff --git a/fluent-syntax/tests/fixtures/formatted/junked/literal_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/literal_expressions.ftl deleted file mode 100644 index 8b45c427..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/literal_expressions.ftl +++ /dev/null @@ -1,3 +0,0 @@ -string-expression = { "abc" } -number-expression = { 123 } -number-expression = { -3.14 } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/member_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/member_expressions.ftl deleted file mode 100644 index 3a1089c8..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/member_expressions.ftl +++ /dev/null @@ -1,23 +0,0 @@ -## Member expressions in placeables. - -# OK Message attributes may be interpolated in values. -message-attribute-expression-placeable = { msg.attr } - -# ERROR Term attributes may not be used for interpolation. - -term-attribute-expression-placeable = {-term.attr} - - -## Member expressions in selectors. - -# OK Term attributes may be used as selectors. -term-attribute-expression-selector = - { -term.attr -> - *[key] Value - } - -# ERROR Message attributes may not be used as selectors. - -message-attribute-expression-selector = {msg.attr -> - *[key] Value -} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/messages.ftl b/fluent-syntax/tests/fixtures/formatted/junked/messages.ftl deleted file mode 100644 index a5bcd1f1..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/messages.ftl +++ /dev/null @@ -1,45 +0,0 @@ -key01 = Value -key02 = Value - .attr = Attribute -key02 = Value - .attr1 = Attribute 1 - .attr2 = Attribute 2 -key03 = - .attr = Attribute -key04 = - .attr1 = Attribute 1 - .attr2 = Attribute 2 -# < whitespace > -key05 = - .attr1 = Attribute 1 -no-whitespace = Value - .attr1 = Attribute 1 -extra-whitespace = Value - .attr1 = Attribute 1 -key06 = { "" } - -# JUNK Missing value - -key07 = - -# JUNK Missing = - -key08 - -KEY09 = Value 09 -key-10 = Value 10 -key_11 = Value 11 -key-12- = Value 12 -key_13_ = Value 13 - -# JUNK Invalid id - -0err-14 = Value 14 - -# JUNK Invalid id - -err-15? = Value 15 - -# JUNK Invalid id - -err-ąę-16 = Value 16 diff --git a/fluent-syntax/tests/fixtures/formatted/junked/mixed_entries.ftl b/fluent-syntax/tests/fixtures/formatted/junked/mixed_entries.ftl deleted file mode 100644 index 57480b45..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/mixed_entries.ftl +++ /dev/null @@ -1,24 +0,0 @@ -# License Comment - - -### Resource Comment - --brand-name = Aurora - -## Group Comment - -key01 = - .attr = Attribute -ą=Invalid identifier -ć=Another one - -# Message Comment -key02 = Value - -# Standalone Comment - - .attr = Dangling attribute - -# There are 5 spaces on the line between key03 and key04. -key03 = Value 03 -key04 = Value 04 diff --git a/fluent-syntax/tests/fixtures/formatted/junked/numbers.ftl b/fluent-syntax/tests/fixtures/formatted/junked/numbers.ftl deleted file mode 100644 index 08d6e6b1..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/numbers.ftl +++ /dev/null @@ -1,32 +0,0 @@ -int-zero = { 0 } -int-positive = { 1 } -int-negative = { -1 } -int-negative-zero = { -0 } -int-positive-padded = { 01 } -int-negative-padded = { -01 } -int-zero-padded = { 00 } -int-negative-zero-padded = { -00 } -float-zero = { 0.0 } -float-positive = { 0.01 } -float-positive-one = { 1.03 } -float-positive-without-fraction = { 1.000 } -float-negative = { -0.01 } -float-negative-one = { -1.03 } -float-negative-zero = { -0.0 } -float-negative-without-fraction = { -1.000 } -float-positive-padded-left = { 01.03 } -float-positive-padded-right = { 1.0300 } -float-positive-padded-both = { 01.0300 } -float-negative-padded-left = { -01.03 } -float-negative-padded-right = { -1.0300 } -float-negative-padded-both = { -01.0300 } - -## ERRORS - -err01 = {1.} -err02 = {.02} -err03 = {1.02.03} -err04 = {1. 02} -err05 = {1 .02} -err06 = {- 1} -err07 = {1,02} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/obsolete.ftl b/fluent-syntax/tests/fixtures/formatted/junked/obsolete.ftl deleted file mode 100644 index e0869e3a..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/obsolete.ftl +++ /dev/null @@ -1,29 +0,0 @@ -### The syntax in this file has been discontinued. It is no longer part of the -### Fluent specification and should not be implemented nor used. We're keeping -### these fixtures around to protect against accidental syntax reuse. - - -## Variant lists. - -message-variant-list = - { - *[key] Value - } - --term-variant-list = - { - *[key] Value - } - - -## Variant expressions. - -message-variant-expression-placeable = {msg[case]} -message-variant-expression-selector = {msg[case] -> - *[key] Value -} - -term-variant-expression-placeable = {-term[case]} -term-variant-expression-selector = {-term[case] -> - *[key] Value -} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/placeables.ftl b/fluent-syntax/tests/fixtures/formatted/junked/placeables.ftl deleted file mode 100644 index 1a2013b9..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/placeables.ftl +++ /dev/null @@ -1,19 +0,0 @@ -nested-placeable = {{ {1} }} -padded-placeable = { 1 } -sparse-placeable = {{ 1 }} - -# ERROR Unmatched opening brace - -unmatched-open1 = { 1 - -# ERROR Unmatched opening brace - -unmatched-open2 = {{ 1 } - -# ERROR Unmatched closing brace - -unmatched-close1 = 1 } - -# ERROR Unmatched closing brace - -unmatched-close2 = { 1 }} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/reference_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/reference_expressions.ftl deleted file mode 100644 index 1f4b8674..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/reference_expressions.ftl +++ /dev/null @@ -1,32 +0,0 @@ -## Reference expressions in placeables. - -message-reference-placeable = { msg } -term-reference-placeable = { -term } -variable-reference-placeable = { $var } -# Function references are invalid outside of call expressions. -# This parses as a valid MessageReference. -function-reference-placeable = { FUN } - -## Reference expressions in selectors. - -variable-reference-selector = - { $var -> - *[key] Value - } - -# ERROR Message values may not be used as selectors. - -message-reference-selector = {msg -> - *[key] Value -} -# ERROR Term values may not be used as selectors. - -term-reference-selector = {-term -> - *[key] Value -} -# ERROR Function references are invalid outside of call expressions, and this -# parses as a MessageReference which isn't a valid selector. - -function-expression-selector = {FUN -> - *[key] Value -} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/select_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/junked/select_expressions.ftl deleted file mode 100644 index 4598442e..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/select_expressions.ftl +++ /dev/null @@ -1,68 +0,0 @@ -new-messages = - { BUILTIN() -> - [0] Zero - *[other] { "" }Other - } -valid-selector-term-attribute = - { -term.case -> - *[key] value - } - -# ERROR Term values are not valid selectors - -invalid-selector-term-value = - { -term -> - *[key] value - } - -# ERROR CallExpressions on Terms are similar to TermReferences - -invalid-selector-term-variant = - { -term(case: "nominative") -> - *[key] value - } - -# ERROR Nested expressions are not valid selectors - -invalid-selector-nested-expression = - { { 3 } -> - *[key] default - } - -# ERROR Select expressions are not valid selectors - -invalid-selector-select-expression = - { { $sel -> - *[key] value - } -> - *[key] default - } - -empty-variant = - { $sel -> - *[key] { "" } - } -reduced-whitespace = - { FOO() -> - *[key] { "" } - } -nested-select = - { $sel -> - *[one] - { $sel -> - *[two] Value - } - } - -# ERROR Missing selector - -missing-selector = - { - *[key] Value - } - -# ERROR Missing line end after variant list - -missing-line-end = - { $sel -> - *[key] Value} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/select_indent.ftl b/fluent-syntax/tests/fixtures/formatted/junked/select_indent.ftl deleted file mode 100644 index 3c21d71f..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/select_indent.ftl +++ /dev/null @@ -1,70 +0,0 @@ -select-1tbs-inline = - { $selector -> - *[key] Value - } -select-1tbs-newline = - { $selector -> - *[key] Value - } -select-1tbs-indent = - { $selector -> - *[key] Value - } -select-allman-inline = - { $selector -> - *[key] Value - [other] Other - } -select-allman-newline = - { $selector -> - *[key] Value - } -select-allman-indent = - { $selector -> - *[key] Value - } -select-gnu-inline = - { $selector -> - *[key] Value - } -select-gnu-newline = - { $selector -> - *[key] Value - } -select-gnu-indent = - { $selector -> - *[key] Value - } -select-no-indent = - { $selector -> - *[key] Value - [other] Other - } -select-no-indent-multiline = - { $selector -> - *[key] - Value - Continued - [other] - Other - Multiline - } - -# ERROR (Multiline text must be indented) - -select-no-indent-multiline = { $selector -> - *[key] Value -Continued without indent. -} - -select-flat = - { $selector -> - *[key] Value - [other] Other - } -# Each line ends with 5 spaces. -select-flat-with-trailing-spaces = - { $selector -> - *[key] Value - [other] Other - } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/sparse_entries.ftl b/fluent-syntax/tests/fixtures/formatted/junked/sparse_entries.ftl deleted file mode 100644 index dfa85945..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/sparse_entries.ftl +++ /dev/null @@ -1,17 +0,0 @@ -key01 = Value -key02 = - .attr = Attribute -key03 = - Value - Continued - - - Over multiple - Lines - .attr = Attribute -key05 = Value -key06 = - { 1 -> - [one] One - *[two] Two - } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/special_chars.ftl b/fluent-syntax/tests/fixtures/formatted/junked/special_chars.ftl deleted file mode 100644 index 5224bad7..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/special_chars.ftl +++ /dev/null @@ -1,14 +0,0 @@ -## OK - -bracket-inline = [Value] -dot-inline = .Value -star-inline = *Value - -## ERRORS - -bracket-newline = - [Value] -dot-newline = - .Value -star-newline = - *Value diff --git a/fluent-syntax/tests/fixtures/formatted/junked/tab.ftl b/fluent-syntax/tests/fixtures/formatted/junked/tab.ftl deleted file mode 100644 index 46b5aa9f..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/tab.ftl +++ /dev/null @@ -1,21 +0,0 @@ -# OK (tab after = is part of the value) -key01 = Value 01 - -# Error (tab before =) - -key02 = Value 02 - -# Error (tab is not a valid indent) - -key03 = - This line isn't properly indented. - -# Partial Error (tab is not a valid indent) -key04 = This line is indented by 4 spaces, - whereas this line by 1 tab. - -# OK (value is a single tab) -key05 = -# OK (attribute value is two tabs) -key06 = - .attr = diff --git a/fluent-syntax/tests/fixtures/formatted/junked/term_parameters.ftl b/fluent-syntax/tests/fixtures/formatted/junked/term_parameters.ftl deleted file mode 100644 index 8ee2ed74..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/term_parameters.ftl +++ /dev/null @@ -1,8 +0,0 @@ --term = - { $arg -> - *[key] Value - } -key01 = { -term } -key02 = { -term() } -key03 = { -term(arg: 1) } -key04 = { -term("positional", narg1: 1, narg2: 2) } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/terms.ftl b/fluent-syntax/tests/fixtures/formatted/junked/terms.ftl deleted file mode 100644 index 4bd9e6cc..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/terms.ftl +++ /dev/null @@ -1,32 +0,0 @@ --term01 = Value - .attr = Attribute --term02 = { "" } - -# JUNK Missing value - --term03 = - .attr = Attribute - -# JUNK Missing value -# < whitespace > - --term04 = - .attr1 = Attribute 1 - -# JUNK Missing value - --term05 = - -# JUNK Missing value -# < whitespace > - --term06 = - -# JUNK Missing = - --term07 - --term08 = Value - .attr = Attribute --term09 = Value - .attr = Attribute diff --git a/fluent-syntax/tests/fixtures/formatted/junked/variables.ftl b/fluent-syntax/tests/fixtures/formatted/junked/variables.ftl deleted file mode 100644 index 1a12cc59..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/variables.ftl +++ /dev/null @@ -1,17 +0,0 @@ -key01 = { $var } -key02 = { $var } -key03 = { $var } -key04 = { $var } - -## Errors - - -# ERROR Missing variable identifier - -err01 = {$} -# ERROR Double $$ - -err02 = {$$var} -# ERROR Invalid first char of the identifier - -err03 = {$-var} diff --git a/fluent-syntax/tests/fixtures/formatted/junked/variant_keys.ftl b/fluent-syntax/tests/fixtures/formatted/junked/variant_keys.ftl deleted file mode 100644 index e3ee17f2..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/variant_keys.ftl +++ /dev/null @@ -1,37 +0,0 @@ -simple-identifier = - { $sel -> - *[key] value - } -identifier-surrounded-by-whitespace = - { $sel -> - *[key] value - } -int-number = - { $sel -> - *[1] value - } -float-number = - { $sel -> - *[3.14] value - } - -# ERROR - -invalid-identifier = - { $sel -> - *[two words] value - } - -# ERROR - -invalid-int = - { $sel -> - *[1 apple] value - } - -# ERROR - -invalid-int = - { $sel -> - *[3.14 apples] value - } diff --git a/fluent-syntax/tests/fixtures/formatted/junked/whitespace_in_value.ftl b/fluent-syntax/tests/fixtures/formatted/junked/whitespace_in_value.ftl deleted file mode 100644 index 0cbcd371..00000000 --- a/fluent-syntax/tests/fixtures/formatted/junked/whitespace_in_value.ftl +++ /dev/null @@ -1,10 +0,0 @@ -# Caution, lines 6 and 7 contain white-space-only lines -key = - first line - - - - - - - last line diff --git a/fluent-syntax/tests/fixtures/formatted/junked/zero_length.ftl b/fluent-syntax/tests/fixtures/formatted/junked/zero_length.ftl deleted file mode 100644 index e69de29b..00000000 diff --git a/fluent-syntax/tests/fixtures/formatted/leading_dots.ftl b/fluent-syntax/tests/fixtures/formatted/leading_dots.ftl deleted file mode 100644 index d63f60e3..00000000 --- a/fluent-syntax/tests/fixtures/formatted/leading_dots.ftl +++ /dev/null @@ -1,46 +0,0 @@ -key01 = .Value -key02 = …Value -key03 = { "." }Value -key04 = { "." }Value -key05 = - Value - { "." }Continued -key06 = .Value -{ "." }Continued -# MESSAGE (value = "Value", attributes = []) -# JUNK (attr .Continued" must have a value) -key07 = Value -# JUNK (attr .Value must have a value) - -# JUNK (attr .Value must have a value) - -key10 = - .Value = - which is an attribute - Continued -key11 = - { "." }Value = which looks like an attribute - Continued -key12 = - .accesskey = A -key13 = - .attribute = .Value -key14 = - .attribute = { "." }Value -key15 = - { 1 -> - [one] .Value - *[other] { "." }Value - } - -# JUNK (variant must have a value) - -# JUNK (unclosed placeable) - -# JUNK (attr .Value must have a value) - -key19 = - .attribute = - Value - Continued -key20 = { "." }Value diff --git a/fluent-syntax/tests/fixtures/formatted/literal_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/literal_expressions.ftl deleted file mode 100644 index 8b45c427..00000000 --- a/fluent-syntax/tests/fixtures/formatted/literal_expressions.ftl +++ /dev/null @@ -1,3 +0,0 @@ -string-expression = { "abc" } -number-expression = { 123 } -number-expression = { -3.14 } diff --git a/fluent-syntax/tests/fixtures/formatted/member_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/member_expressions.ftl deleted file mode 100644 index 809c2608..00000000 --- a/fluent-syntax/tests/fixtures/formatted/member_expressions.ftl +++ /dev/null @@ -1,17 +0,0 @@ -## Member expressions in placeables. - -# OK Message attributes may be interpolated in values. -message-attribute-expression-placeable = { msg.attr } - -# ERROR Term attributes may not be used for interpolation. - -## Member expressions in selectors. - -# OK Term attributes may be used as selectors. -term-attribute-expression-selector = - { -term.attr -> - *[key] Value - } - -# ERROR Message attributes may not be used as selectors. - diff --git a/fluent-syntax/tests/fixtures/formatted/messages.ftl b/fluent-syntax/tests/fixtures/formatted/messages.ftl deleted file mode 100644 index 72403bd3..00000000 --- a/fluent-syntax/tests/fixtures/formatted/messages.ftl +++ /dev/null @@ -1,36 +0,0 @@ -key01 = Value -key02 = Value - .attr = Attribute -key02 = Value - .attr1 = Attribute 1 - .attr2 = Attribute 2 -key03 = - .attr = Attribute -key04 = - .attr1 = Attribute 1 - .attr2 = Attribute 2 -# < whitespace > -key05 = - .attr1 = Attribute 1 -no-whitespace = Value - .attr1 = Attribute 1 -extra-whitespace = Value - .attr1 = Attribute 1 -key06 = { "" } - -# JUNK Missing value - -# JUNK Missing = - -KEY09 = Value 09 -key-10 = Value 10 -key_11 = Value 11 -key-12- = Value 12 -key_13_ = Value 13 - -# JUNK Invalid id - -# JUNK Invalid id - -# JUNK Invalid id - diff --git a/fluent-syntax/tests/fixtures/formatted/mixed_entries.ftl b/fluent-syntax/tests/fixtures/formatted/mixed_entries.ftl deleted file mode 100644 index f8e54c29..00000000 --- a/fluent-syntax/tests/fixtures/formatted/mixed_entries.ftl +++ /dev/null @@ -1,19 +0,0 @@ -# License Comment - - -### Resource Comment - --brand-name = Aurora - -## Group Comment - -key01 = - .attr = Attribute -# Message Comment -key02 = Value - -# Standalone Comment - -# There are 5 spaces on the line between key03 and key04. -key03 = Value 03 -key04 = Value 04 diff --git a/fluent-syntax/tests/fixtures/formatted/numbers.ftl b/fluent-syntax/tests/fixtures/formatted/numbers.ftl deleted file mode 100644 index 521f5a23..00000000 --- a/fluent-syntax/tests/fixtures/formatted/numbers.ftl +++ /dev/null @@ -1,25 +0,0 @@ -int-zero = { 0 } -int-positive = { 1 } -int-negative = { -1 } -int-negative-zero = { -0 } -int-positive-padded = { 01 } -int-negative-padded = { -01 } -int-zero-padded = { 00 } -int-negative-zero-padded = { -00 } -float-zero = { 0.0 } -float-positive = { 0.01 } -float-positive-one = { 1.03 } -float-positive-without-fraction = { 1.000 } -float-negative = { -0.01 } -float-negative-one = { -1.03 } -float-negative-zero = { -0.0 } -float-negative-without-fraction = { -1.000 } -float-positive-padded-left = { 01.03 } -float-positive-padded-right = { 1.0300 } -float-positive-padded-both = { 01.0300 } -float-negative-padded-left = { -01.03 } -float-negative-padded-right = { -1.0300 } -float-negative-padded-both = { -01.0300 } - -## ERRORS - diff --git a/fluent-syntax/tests/fixtures/formatted/obsolete.ftl b/fluent-syntax/tests/fixtures/formatted/obsolete.ftl deleted file mode 100644 index 314a35ef..00000000 --- a/fluent-syntax/tests/fixtures/formatted/obsolete.ftl +++ /dev/null @@ -1,9 +0,0 @@ -### The syntax in this file has been discontinued. It is no longer part of the -### Fluent specification and should not be implemented nor used. We're keeping -### these fixtures around to protect against accidental syntax reuse. - - -## Variant lists. - -## Variant expressions. - diff --git a/fluent-syntax/tests/fixtures/formatted/placeables.ftl b/fluent-syntax/tests/fixtures/formatted/placeables.ftl deleted file mode 100644 index 6a5167be..00000000 --- a/fluent-syntax/tests/fixtures/formatted/placeables.ftl +++ /dev/null @@ -1,12 +0,0 @@ -nested-placeable = {{ {1} }} -padded-placeable = { 1 } -sparse-placeable = {{ 1 }} - -# ERROR Unmatched opening brace - -# ERROR Unmatched opening brace - -# ERROR Unmatched closing brace - -# ERROR Unmatched closing brace - diff --git a/fluent-syntax/tests/fixtures/formatted/reference_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/reference_expressions.ftl deleted file mode 100644 index 5132517f..00000000 --- a/fluent-syntax/tests/fixtures/formatted/reference_expressions.ftl +++ /dev/null @@ -1,23 +0,0 @@ -## Reference expressions in placeables. - -message-reference-placeable = { msg } -term-reference-placeable = { -term } -variable-reference-placeable = { $var } -# Function references are invalid outside of call expressions. -# This parses as a valid MessageReference. -function-reference-placeable = { FUN } - -## Reference expressions in selectors. - -variable-reference-selector = - { $var -> - *[key] Value - } - -# ERROR Message values may not be used as selectors. - -# ERROR Term values may not be used as selectors. - -# ERROR Function references are invalid outside of call expressions, and this -# parses as a MessageReference which isn't a valid selector. - diff --git a/fluent-syntax/tests/fixtures/formatted/select_expressions.ftl b/fluent-syntax/tests/fixtures/formatted/select_expressions.ftl deleted file mode 100644 index 8e1021b4..00000000 --- a/fluent-syntax/tests/fixtures/formatted/select_expressions.ftl +++ /dev/null @@ -1,38 +0,0 @@ -new-messages = - { BUILTIN() -> - [0] Zero - *[other] { "" }Other - } -valid-selector-term-attribute = - { -term.case -> - *[key] value - } - -# ERROR Term values are not valid selectors - -# ERROR CallExpressions on Terms are similar to TermReferences - -# ERROR Nested expressions are not valid selectors - -# ERROR Select expressions are not valid selectors - -empty-variant = - { $sel -> - *[key] { "" } - } -reduced-whitespace = - { FOO() -> - *[key] { "" } - } -nested-select = - { $sel -> - *[one] - { $sel -> - *[two] Value - } - } - -# ERROR Missing selector - -# ERROR Missing line end after variant list - diff --git a/fluent-syntax/tests/fixtures/formatted/select_indent.ftl b/fluent-syntax/tests/fixtures/formatted/select_indent.ftl deleted file mode 100644 index 9aa2a995..00000000 --- a/fluent-syntax/tests/fixtures/formatted/select_indent.ftl +++ /dev/null @@ -1,65 +0,0 @@ -select-1tbs-inline = - { $selector -> - *[key] Value - } -select-1tbs-newline = - { $selector -> - *[key] Value - } -select-1tbs-indent = - { $selector -> - *[key] Value - } -select-allman-inline = - { $selector -> - *[key] Value - [other] Other - } -select-allman-newline = - { $selector -> - *[key] Value - } -select-allman-indent = - { $selector -> - *[key] Value - } -select-gnu-inline = - { $selector -> - *[key] Value - } -select-gnu-newline = - { $selector -> - *[key] Value - } -select-gnu-indent = - { $selector -> - *[key] Value - } -select-no-indent = - { $selector -> - *[key] Value - [other] Other - } -select-no-indent-multiline = - { $selector -> - *[key] - Value - Continued - [other] - Other - Multiline - } - -# ERROR (Multiline text must be indented) - -select-flat = - { $selector -> - *[key] Value - [other] Other - } -# Each line ends with 5 spaces. -select-flat-with-trailing-spaces = - { $selector -> - *[key] Value - [other] Other - } diff --git a/fluent-syntax/tests/fixtures/formatted/sparse_entries.ftl b/fluent-syntax/tests/fixtures/formatted/sparse_entries.ftl deleted file mode 100644 index dfa85945..00000000 --- a/fluent-syntax/tests/fixtures/formatted/sparse_entries.ftl +++ /dev/null @@ -1,17 +0,0 @@ -key01 = Value -key02 = - .attr = Attribute -key03 = - Value - Continued - - - Over multiple - Lines - .attr = Attribute -key05 = Value -key06 = - { 1 -> - [one] One - *[two] Two - } diff --git a/fluent-syntax/tests/fixtures/formatted/special_chars.ftl b/fluent-syntax/tests/fixtures/formatted/special_chars.ftl deleted file mode 100644 index ab32df9d..00000000 --- a/fluent-syntax/tests/fixtures/formatted/special_chars.ftl +++ /dev/null @@ -1,8 +0,0 @@ -## OK - -bracket-inline = [Value] -dot-inline = .Value -star-inline = *Value - -## ERRORS - diff --git a/fluent-syntax/tests/fixtures/formatted/tab.ftl b/fluent-syntax/tests/fixtures/formatted/tab.ftl deleted file mode 100644 index bbbd7332..00000000 --- a/fluent-syntax/tests/fixtures/formatted/tab.ftl +++ /dev/null @@ -1,14 +0,0 @@ -# OK (tab after = is part of the value) -key01 = Value 01 - -# Error (tab before =) - -# Error (tab is not a valid indent) - -# Partial Error (tab is not a valid indent) -key04 = This line is indented by 4 spaces, -# OK (value is a single tab) -key05 = -# OK (attribute value is two tabs) -key06 = - .attr = diff --git a/fluent-syntax/tests/fixtures/formatted/term_parameters.ftl b/fluent-syntax/tests/fixtures/formatted/term_parameters.ftl deleted file mode 100644 index 8ee2ed74..00000000 --- a/fluent-syntax/tests/fixtures/formatted/term_parameters.ftl +++ /dev/null @@ -1,8 +0,0 @@ --term = - { $arg -> - *[key] Value - } -key01 = { -term } -key02 = { -term() } -key03 = { -term(arg: 1) } -key04 = { -term("positional", narg1: 1, narg2: 2) } diff --git a/fluent-syntax/tests/fixtures/formatted/terms.ftl b/fluent-syntax/tests/fixtures/formatted/terms.ftl deleted file mode 100644 index 37d68113..00000000 --- a/fluent-syntax/tests/fixtures/formatted/terms.ftl +++ /dev/null @@ -1,20 +0,0 @@ --term01 = Value - .attr = Attribute --term02 = { "" } - -# JUNK Missing value - -# JUNK Missing value -# < whitespace > - -# JUNK Missing value - -# JUNK Missing value -# < whitespace > - -# JUNK Missing = - --term08 = Value - .attr = Attribute --term09 = Value - .attr = Attribute diff --git a/fluent-syntax/tests/fixtures/formatted/variables.ftl b/fluent-syntax/tests/fixtures/formatted/variables.ftl deleted file mode 100644 index 25d58359..00000000 --- a/fluent-syntax/tests/fixtures/formatted/variables.ftl +++ /dev/null @@ -1,14 +0,0 @@ -key01 = { $var } -key02 = { $var } -key03 = { $var } -key04 = { $var } - -## Errors - - -# ERROR Missing variable identifier - -# ERROR Double $$ - -# ERROR Invalid first char of the identifier - diff --git a/fluent-syntax/tests/fixtures/formatted/variant_keys.ftl b/fluent-syntax/tests/fixtures/formatted/variant_keys.ftl deleted file mode 100644 index d0313bcc..00000000 --- a/fluent-syntax/tests/fixtures/formatted/variant_keys.ftl +++ /dev/null @@ -1,23 +0,0 @@ -simple-identifier = - { $sel -> - *[key] value - } -identifier-surrounded-by-whitespace = - { $sel -> - *[key] value - } -int-number = - { $sel -> - *[1] value - } -float-number = - { $sel -> - *[3.14] value - } - -# ERROR - -# ERROR - -# ERROR - diff --git a/fluent-syntax/tests/fixtures/formatted/whitespace_in_value.ftl b/fluent-syntax/tests/fixtures/formatted/whitespace_in_value.ftl deleted file mode 100644 index 0cbcd371..00000000 --- a/fluent-syntax/tests/fixtures/formatted/whitespace_in_value.ftl +++ /dev/null @@ -1,10 +0,0 @@ -# Caution, lines 6 and 7 contain white-space-only lines -key = - first line - - - - - - - last line diff --git a/fluent-syntax/tests/fixtures/formatted/zero_length.ftl b/fluent-syntax/tests/fixtures/formatted/zero_length.ftl deleted file mode 100644 index e69de29b..00000000 diff --git a/fluent-syntax/tests/serializer_fixtures.rs b/fluent-syntax/tests/serializer_fixtures.rs index c961ccef..ab5b7225 100644 --- a/fluent-syntax/tests/serializer_fixtures.rs +++ b/fluent-syntax/tests/serializer_fixtures.rs @@ -1,3 +1,4 @@ +use fluent_syntax::ast::{Entry, Resource}; use glob::glob; use std::ffi::OsStr; use std::fs; @@ -21,6 +22,19 @@ fn is_ignored(path: &Path) -> bool { .unwrap_or_default() } +fn clone_without_junk<'a>(original: &Resource<&'a str>) -> Resource<&'a str> { + Resource { + body: original + .body + .iter() + .filter(|entry| !matches!(entry, Entry::Junk { .. })) + .cloned() + .collect(), + #[cfg(feature = "spans")] + span: original.span, + } +} + #[test] fn roundtrip_normalized_fixtures() { for entry in glob("./tests/fixtures/normalized/*.ftl").expect("Failed to read glob pattern") { @@ -45,33 +59,15 @@ fn roundtrip_unnormalized_fixtures() { let content = fs::read_to_string(&path).expect("Failed to read file"); let parsed = parse(content.as_str()).unwrap_or_else(|(res, _)| res); - + let parsed_without_junk = clone_without_junk(&parsed); let reserialized = serialize_with_options(&parsed, Options { with_junk: true }); let reserialized_without_junk = serialize_with_options(&parsed, Options { with_junk: false }); - - let formatted_path = path.parent().unwrap().join("formatted"); - - let formatted_content = fs::read_to_string( - formatted_path - .join("junked") - .join(path.file_name().unwrap()), - ) - .unwrap(); - assert_eq!(formatted_content, reserialized); - let formatted = parse(formatted_content.as_str()).unwrap_or_else(|(res, _)| res); - - let formatted_content_without_junk = - fs::read_to_string(formatted_path.join(path.file_name().unwrap())).unwrap(); - assert_eq!(formatted_content_without_junk, reserialized_without_junk); - let formatted_without_junk = - parse(formatted_content_without_junk.as_str()).unwrap_or_else(|(res, _)| res); - let reparsed = parse(reserialized.as_str()).unwrap_or_else(|(res, _)| res); let reparsed_without_junk = parse(reserialized_without_junk.as_str()).unwrap_or_else(|(res, _)| res); - assert_eq!(formatted_without_junk, reparsed_without_junk); - assert_eq!(formatted, reparsed); + assert_eq!(reparsed_without_junk, parsed_without_junk); + assert_eq!(reparsed, parsed); } } From 1a16d2c34be8fbb2585a66473276e099b3182cea Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 22 May 2025 14:43:53 +0300 Subject: [PATCH 08/11] fixup! wrap Range...use clone to keep serializing working without Copy trait --- fluent-syntax/tests/serializer_fixtures.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fluent-syntax/tests/serializer_fixtures.rs b/fluent-syntax/tests/serializer_fixtures.rs index ab5b7225..b10c2803 100644 --- a/fluent-syntax/tests/serializer_fixtures.rs +++ b/fluent-syntax/tests/serializer_fixtures.rs @@ -31,7 +31,7 @@ fn clone_without_junk<'a>(original: &Resource<&'a str>) -> Resource<&'a str> { .cloned() .collect(), #[cfg(feature = "spans")] - span: original.span, + span: original.span.clone(), } } From c7c120a1bca2190477a42848343bc6dfdab85f84 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 21 May 2025 18:45:00 +0300 Subject: [PATCH 09/11] fixup! Create generic ftl serializer (#241) --- fluent-syntax/tests/serializer_fixtures.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fluent-syntax/tests/serializer_fixtures.rs b/fluent-syntax/tests/serializer_fixtures.rs index b10c2803..58924efe 100644 --- a/fluent-syntax/tests/serializer_fixtures.rs +++ b/fluent-syntax/tests/serializer_fixtures.rs @@ -46,9 +46,9 @@ fn roundtrip_normalized_fixtures() { } } -/// Compares a parsed AST with a parsed, serialized and reparsed AST, as these fixtures -/// contain unnormalized syntax that is not supposed to be preserved on a roundtrip. -/// Tests both parsing with and without junk. +/// Compares a parsed AST with a parsed, serialized, and re-parsed AST, as these fixtures +/// contain unnormalized syntax that is not supposed to be preserved on a round-trip. +/// Tests parsing both with and without junk. #[test] fn roundtrip_unnormalized_fixtures() { for entry in glob("./tests/fixtures/*.ftl").expect("Failed to read glob pattern") { From cf2c4275592741d80cae2f60a3f4c78f87113f88 Mon Sep 17 00:00:00 2001 From: Ertanic Date: Fri, 23 May 2025 09:34:36 +0300 Subject: [PATCH 10/11] Fix parse_fixtures_compare test --- .../tests/fixtures/any_char.spans.json | 128 + .../tests/fixtures/astral.spans.json | 346 +++ .../fixtures/call_expressions.spans.json | 2555 +++++++++++++++++ .../fixtures/callee_expressions.spans.json | 524 ++++ .../tests/fixtures/comments.spans.json | 166 ++ fluent-syntax/tests/fixtures/cr.spans.json | 18 + fluent-syntax/tests/fixtures/crlf.spans.json | 164 ++ .../tests/fixtures/eof_comment.spans.json | 28 + .../tests/fixtures/eof_empty.spans.json | 7 + .../tests/fixtures/eof_id.spans.json | 26 + .../tests/fixtures/eof_id_equals.spans.json | 26 + .../tests/fixtures/eof_junk.spans.json | 26 + .../tests/fixtures/eof_value.spans.json | 50 + .../fixtures/escaped_characters.spans.json | 824 ++++++ fluent-syntax/tests/fixtures/junk.spans.json | 135 + .../tests/fixtures/leading_dots.spans.json | 957 ++++++ .../fixtures/literal_expressions.spans.json | 143 + .../fixtures/member_expressions.spans.json | 231 ++ .../tests/fixtures/messages.spans.json | 790 +++++ .../tests/fixtures/mixed_entries.spans.json | 255 ++ .../fixtures/multiline_values.spans.json | 782 +++++ .../tests/fixtures/numbers.spans.json | 1064 +++++++ .../tests/fixtures/obsolete.spans.json | 88 + .../tests/fixtures/placeables.spans.json | 254 ++ .../fixtures/reference_expressions.spans.json | 385 +++ .../fixtures/select_expressions.spans.json | 699 +++++ .../tests/fixtures/select_indent.spans.json | 1323 +++++++++ .../tests/fixtures/sparse_entries.spans.json | 332 +++ .../tests/fixtures/special_chars.spans.json | 148 + fluent-syntax/tests/fixtures/tab.spans.json | 227 ++ .../tests/fixtures/term_parameters.spans.json | 406 +++ fluent-syntax/tests/fixtures/terms.spans.json | 331 +++ .../tests/fixtures/variables.spans.json | 276 ++ .../tests/fixtures/variant_keys.spans.json | 402 +++ .../fixtures/whitespace_in_value.spans.json | 104 + .../tests/fixtures/zero_length.spans.json | 7 + fluent-syntax/tests/helper/mod.rs | 10 +- fluent-syntax/tests/parser_fixtures.rs | 10 + 38 files changed, 14242 insertions(+), 5 deletions(-) create mode 100644 fluent-syntax/tests/fixtures/any_char.spans.json create mode 100644 fluent-syntax/tests/fixtures/astral.spans.json create mode 100644 fluent-syntax/tests/fixtures/call_expressions.spans.json create mode 100644 fluent-syntax/tests/fixtures/callee_expressions.spans.json create mode 100644 fluent-syntax/tests/fixtures/comments.spans.json create mode 100644 fluent-syntax/tests/fixtures/cr.spans.json create mode 100644 fluent-syntax/tests/fixtures/crlf.spans.json create mode 100644 fluent-syntax/tests/fixtures/eof_comment.spans.json create mode 100644 fluent-syntax/tests/fixtures/eof_empty.spans.json create mode 100644 fluent-syntax/tests/fixtures/eof_id.spans.json create mode 100644 fluent-syntax/tests/fixtures/eof_id_equals.spans.json create mode 100644 fluent-syntax/tests/fixtures/eof_junk.spans.json create mode 100644 fluent-syntax/tests/fixtures/eof_value.spans.json create mode 100644 fluent-syntax/tests/fixtures/escaped_characters.spans.json create mode 100644 fluent-syntax/tests/fixtures/junk.spans.json create mode 100644 fluent-syntax/tests/fixtures/leading_dots.spans.json create mode 100644 fluent-syntax/tests/fixtures/literal_expressions.spans.json create mode 100644 fluent-syntax/tests/fixtures/member_expressions.spans.json create mode 100644 fluent-syntax/tests/fixtures/messages.spans.json create mode 100644 fluent-syntax/tests/fixtures/mixed_entries.spans.json create mode 100644 fluent-syntax/tests/fixtures/multiline_values.spans.json create mode 100644 fluent-syntax/tests/fixtures/numbers.spans.json create mode 100644 fluent-syntax/tests/fixtures/obsolete.spans.json create mode 100644 fluent-syntax/tests/fixtures/placeables.spans.json create mode 100644 fluent-syntax/tests/fixtures/reference_expressions.spans.json create mode 100644 fluent-syntax/tests/fixtures/select_expressions.spans.json create mode 100644 fluent-syntax/tests/fixtures/select_indent.spans.json create mode 100644 fluent-syntax/tests/fixtures/sparse_entries.spans.json create mode 100644 fluent-syntax/tests/fixtures/special_chars.spans.json create mode 100644 fluent-syntax/tests/fixtures/tab.spans.json create mode 100644 fluent-syntax/tests/fixtures/term_parameters.spans.json create mode 100644 fluent-syntax/tests/fixtures/terms.spans.json create mode 100644 fluent-syntax/tests/fixtures/variables.spans.json create mode 100644 fluent-syntax/tests/fixtures/variant_keys.spans.json create mode 100644 fluent-syntax/tests/fixtures/whitespace_in_value.spans.json create mode 100644 fluent-syntax/tests/fixtures/zero_length.spans.json diff --git a/fluent-syntax/tests/fixtures/any_char.spans.json b/fluent-syntax/tests/fixtures/any_char.spans.json new file mode 100644 index 00000000..73ea01a1 --- /dev/null +++ b/fluent-syntax/tests/fixtures/any_char.spans.json @@ -0,0 +1,128 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "control0", + "span": { + "start": 30, + "end": 38 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "abc\u0007def", + "span": { + "start": 41, + "end": 49 + } + } + ], + "span": { + "start": 41, + "end": 50 + } + }, + "attributes": [], + "comment": { + "content": [ + " ↓ BEL, U+0007" + ], + "span": { + "start": 0, + "end": 29 + } + }, + "span": { + "start": 30, + "end": 50 + } + }, + { + "type": "Message", + "id": { + "name": "delete", + "span": { + "start": 78, + "end": 84 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "abcdef", + "span": { + "start": 87, + "end": 95 + } + } + ], + "span": { + "start": 87, + "end": 96 + } + }, + "attributes": [], + "comment": { + "content": [ + " ↓ DEL, U+007F" + ], + "span": { + "start": 50, + "end": 77 + } + }, + "span": { + "start": 78, + "end": 96 + } + }, + { + "type": "Message", + "id": { + "name": "control1", + "span": { + "start": 126, + "end": 134 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "abc‚def", + "span": { + "start": 137, + "end": 146 + } + } + ], + "span": { + "start": 137, + "end": 146 + } + }, + "attributes": [], + "comment": { + "content": [ + " ↓ BPM, U+0082" + ], + "span": { + "start": 96, + "end": 125 + } + }, + "span": { + "start": 126, + "end": 146 + } + } + ], + "span": { + "start": 0, + "end": 146 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/astral.spans.json b/fluent-syntax/tests/fixtures/astral.spans.json new file mode 100644 index 00000000..89581478 --- /dev/null +++ b/fluent-syntax/tests/fixtures/astral.spans.json @@ -0,0 +1,346 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "face-with-tears-of-joy", + "span": { + "start": 0, + "end": 22 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "😂", + "span": { + "start": 25, + "end": 30 + } + } + ], + "span": { + "start": 25, + "end": 30 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 30 + } + }, + { + "type": "Message", + "id": { + "name": "tetragram-for-centre", + "span": { + "start": 30, + "end": 50 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "𝌆", + "span": { + "start": 53, + "end": 58 + } + } + ], + "span": { + "start": 53, + "end": 59 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 30, + "end": 59 + } + }, + { + "type": "Message", + "id": { + "name": "surrogates-in-text", + "span": { + "start": 59, + "end": 77 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "\\uD83D\\uDE02", + "span": { + "start": 80, + "end": 93 + } + } + ], + "span": { + "start": 80, + "end": 93 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 59, + "end": 93 + } + }, + { + "type": "Message", + "id": { + "name": "surrogates-in-string", + "span": { + "start": 93, + "end": 113 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\uD83D\\uDE02", + "span": { + "start": 117, + "end": 131 + } + }, + { + "start": 117, + "end": 131 + } + ], + "span": { + "start": 116, + "end": 131 + } + } + ], + "span": { + "start": 116, + "end": 133 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 93, + "end": 133 + } + }, + { + "type": "Message", + "id": { + "name": "surrogates-in-adjacent-strings", + "span": { + "start": 133, + "end": 163 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\uD83D", + "span": { + "start": 167, + "end": 175 + } + }, + { + "start": 167, + "end": 175 + } + ], + "span": { + "start": 166, + "end": 175 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\uDE02", + "span": { + "start": 177, + "end": 185 + } + }, + { + "start": 177, + "end": 185 + } + ], + "span": { + "start": 176, + "end": 185 + } + } + ], + "span": { + "start": 166, + "end": 188 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 133, + "end": 188 + } + }, + { + "type": "Message", + "id": { + "name": "emoji-in-text", + "span": { + "start": 188, + "end": 201 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A face 😂 with tears of joy.", + "span": { + "start": 204, + "end": 235 + } + } + ], + "span": { + "start": 204, + "end": 235 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 188, + "end": 235 + } + }, + { + "type": "Message", + "id": { + "name": "emoji-in-string", + "span": { + "start": 235, + "end": 250 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "A face 😂 with tears of joy.", + "span": { + "start": 254, + "end": 286 + } + }, + { + "start": 254, + "end": 286 + } + ], + "span": { + "start": 253, + "end": 286 + } + } + ], + "span": { + "start": 253, + "end": 289 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 235, + "end": 289 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Invalid identifier" + ], + "span": { + "start": 289, + "end": 315 + } + }, + { + "type": "Junk", + "content": "err-😂 = Value\n\n", + "span": { + "start": 316, + "end": 334 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Invalid expression" + ], + "span": { + "start": 334, + "end": 360 + } + }, + { + "type": "Junk", + "content": "err-invalid-expression = { 😂 }\n\n", + "span": { + "start": 361, + "end": 396 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Invalid variant key" + ], + "span": { + "start": 396, + "end": 423 + } + }, + { + "type": "Junk", + "content": "err-invalid-variant-key = { $sel ->\n *[😂] Value\n}\n", + "span": { + "start": 424, + "end": 480 + } + } + ], + "span": { + "start": 0, + "end": 480 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/call_expressions.spans.json b/fluent-syntax/tests/fixtures/call_expressions.spans.json new file mode 100644 index 00000000..f83a198c --- /dev/null +++ b/fluent-syntax/tests/fixtures/call_expressions.spans.json @@ -0,0 +1,2555 @@ +{ + "body": [ + { + "type": "GroupComment", + "content": [ + "Function names" + ], + "span": { + "start": 0, + "end": 17 + } + }, + { + "type": "Message", + "id": { + "name": "valid-func-name-01", + "span": { + "start": 19, + "end": 37 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN1", + "span": { + "start": 41, + "end": 45 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 45, + "end": 47 + } + }, + "span": { + "start": 41, + "end": 47 + } + }, + { + "start": 41, + "end": 47 + } + ], + "span": { + "start": 40, + "end": 47 + } + } + ], + "span": { + "start": 40, + "end": 49 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 19, + "end": 49 + } + }, + { + "type": "Message", + "id": { + "name": "valid-func-name-02", + "span": { + "start": 49, + "end": 67 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN_FUN", + "span": { + "start": 71, + "end": 78 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 78, + "end": 80 + } + }, + "span": { + "start": 71, + "end": 80 + } + }, + { + "start": 71, + "end": 80 + } + ], + "span": { + "start": 70, + "end": 80 + } + } + ], + "span": { + "start": 70, + "end": 82 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 49, + "end": 82 + } + }, + { + "type": "Message", + "id": { + "name": "valid-func-name-03", + "span": { + "start": 82, + "end": 100 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN-FUN", + "span": { + "start": 104, + "end": 111 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 111, + "end": 113 + } + }, + "span": { + "start": 104, + "end": 113 + } + }, + { + "start": 104, + "end": 113 + } + ], + "span": { + "start": 103, + "end": 113 + } + } + ], + "span": { + "start": 103, + "end": 116 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 82, + "end": 116 + } + }, + { + "type": "Comment", + "content": [ + "JUNK 0 is not a valid Identifier start" + ], + "span": { + "start": 116, + "end": 156 + } + }, + { + "type": "Junk", + "content": "invalid-func-name-01 = {0FUN()}\n", + "span": { + "start": 157, + "end": 189 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Function names may not be lowercase" + ], + "span": { + "start": 189, + "end": 231 + } + }, + { + "type": "Junk", + "content": "invalid-func-name-02 = {fun()}\n", + "span": { + "start": 232, + "end": 263 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Function names may not contain lowercase character" + ], + "span": { + "start": 263, + "end": 320 + } + }, + { + "type": "Junk", + "content": "invalid-func-name-03 = {Fun()}\n", + "span": { + "start": 321, + "end": 352 + } + }, + { + "type": "Comment", + "content": [ + "JUNK ? is not a valid Identifier character" + ], + "span": { + "start": 352, + "end": 396 + } + }, + { + "type": "Junk", + "content": "invalid-func-name-04 = {FUN?()}\n\n", + "span": { + "start": 397, + "end": 430 + } + }, + { + "type": "GroupComment", + "content": [ + "Arguments" + ], + "span": { + "start": 430, + "end": 442 + } + }, + { + "type": "Message", + "id": { + "name": "positional-args", + "span": { + "start": 444, + "end": 459 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 463, + "end": 466 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 467, + "end": 468 + } + }, + { + "type": "StringLiteral", + "value": "a", + "span": { + "start": 470, + "end": 473 + } + }, + { + "type": "MessageReference", + "id": { + "name": "msg", + "span": { + "start": 475, + "end": 478 + } + }, + "attribute": null, + "span": { + "start": 475, + "end": 478 + } + } + ], + "named": [], + "span": { + "start": 466, + "end": 479 + } + }, + "span": { + "start": 463, + "end": 479 + } + }, + { + "start": 463, + "end": 479 + } + ], + "span": { + "start": 462, + "end": 479 + } + } + ], + "span": { + "start": 462, + "end": 481 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 444, + "end": 481 + } + }, + { + "type": "Message", + "id": { + "name": "named-args", + "span": { + "start": 481, + "end": 491 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 495, + "end": 498 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "x", + "span": { + "start": 499, + "end": 500 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 502, + "end": 503 + } + }, + "span": { + "start": 499, + "end": 503 + } + }, + { + "type": "NamedArgument", + "name": { + "name": "y", + "span": { + "start": 505, + "end": 506 + } + }, + "value": { + "type": "StringLiteral", + "value": "Y", + "span": { + "start": 508, + "end": 511 + } + }, + "span": { + "start": 505, + "end": 511 + } + } + ], + "span": { + "start": 498, + "end": 512 + } + }, + "span": { + "start": 495, + "end": 512 + } + }, + { + "start": 495, + "end": 512 + } + ], + "span": { + "start": 494, + "end": 512 + } + } + ], + "span": { + "start": 494, + "end": 514 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 481, + "end": 514 + } + }, + { + "type": "Message", + "id": { + "name": "dense-named-args", + "span": { + "start": 514, + "end": 530 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 534, + "end": 537 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "x", + "span": { + "start": 538, + "end": 539 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 540, + "end": 541 + } + }, + "span": { + "start": 538, + "end": 541 + } + }, + { + "type": "NamedArgument", + "name": { + "name": "y", + "span": { + "start": 543, + "end": 544 + } + }, + "value": { + "type": "StringLiteral", + "value": "Y", + "span": { + "start": 545, + "end": 548 + } + }, + "span": { + "start": 543, + "end": 548 + } + } + ], + "span": { + "start": 537, + "end": 549 + } + }, + "span": { + "start": 534, + "end": 549 + } + }, + { + "start": 534, + "end": 549 + } + ], + "span": { + "start": 533, + "end": 549 + } + } + ], + "span": { + "start": 533, + "end": 551 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 514, + "end": 551 + } + }, + { + "type": "Message", + "id": { + "name": "mixed-args", + "span": { + "start": 551, + "end": 561 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 565, + "end": 568 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 569, + "end": 570 + } + }, + { + "type": "StringLiteral", + "value": "a", + "span": { + "start": 572, + "end": 575 + } + }, + { + "type": "MessageReference", + "id": { + "name": "msg", + "span": { + "start": 577, + "end": 580 + } + }, + "attribute": null, + "span": { + "start": 577, + "end": 580 + } + } + ], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "x", + "span": { + "start": 582, + "end": 583 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 585, + "end": 586 + } + }, + "span": { + "start": 582, + "end": 586 + } + }, + { + "type": "NamedArgument", + "name": { + "name": "y", + "span": { + "start": 588, + "end": 589 + } + }, + "value": { + "type": "StringLiteral", + "value": "Y", + "span": { + "start": 591, + "end": 594 + } + }, + "span": { + "start": 588, + "end": 594 + } + } + ], + "span": { + "start": 568, + "end": 595 + } + }, + "span": { + "start": 565, + "end": 595 + } + }, + { + "start": 565, + "end": 595 + } + ], + "span": { + "start": 564, + "end": 595 + } + } + ], + "span": { + "start": 564, + "end": 598 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 551, + "end": 598 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Positional arg must not follow keyword args" + ], + "span": { + "start": 598, + "end": 649 + } + }, + { + "type": "Junk", + "content": "shuffled-args = {FUN(1, x: 1, \"a\", y: \"Y\", msg)}\n\n", + "span": { + "start": 650, + "end": 700 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Named arguments must be unique" + ], + "span": { + "start": 700, + "end": 738 + } + }, + { + "type": "Junk", + "content": "duplicate-named-args = {FUN(x: 1, x: \"X\")}\n\n\n", + "span": { + "start": 739, + "end": 784 + } + }, + { + "type": "GroupComment", + "content": [ + "Whitespace around arguments" + ], + "span": { + "start": 784, + "end": 814 + } + }, + { + "type": "Message", + "id": { + "name": "sparse-inline-call", + "span": { + "start": 816, + "end": 834 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 838, + "end": 841 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "StringLiteral", + "value": "a", + "span": { + "start": 849, + "end": 852 + } + }, + { + "type": "MessageReference", + "id": { + "name": "msg", + "span": { + "start": 856, + "end": 859 + } + }, + "attribute": null, + "span": { + "start": 856, + "end": 859 + } + } + ], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "x", + "span": { + "start": 863, + "end": 864 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 866, + "end": 867 + } + }, + "span": { + "start": 863, + "end": 867 + } + } + ], + "span": { + "start": 846, + "end": 871 + } + }, + "span": { + "start": 838, + "end": 871 + } + }, + { + "start": 838, + "end": 871 + } + ], + "span": { + "start": 837, + "end": 871 + } + } + ], + "span": { + "start": 837, + "end": 873 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 816, + "end": 873 + } + }, + { + "type": "Message", + "id": { + "name": "empty-inline-call", + "span": { + "start": 873, + "end": 890 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 894, + "end": 897 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 897, + "end": 901 + } + }, + "span": { + "start": 894, + "end": 901 + } + }, + { + "start": 894, + "end": 901 + } + ], + "span": { + "start": 893, + "end": 901 + } + } + ], + "span": { + "start": 893, + "end": 903 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 873, + "end": 903 + } + }, + { + "type": "Message", + "id": { + "name": "multiline-call", + "span": { + "start": 903, + "end": 917 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 921, + "end": 924 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "StringLiteral", + "value": "a", + "span": { + "start": 934, + "end": 937 + } + }, + { + "type": "MessageReference", + "id": { + "name": "msg", + "span": { + "start": 947, + "end": 950 + } + }, + "attribute": null, + "span": { + "start": 947, + "end": 950 + } + } + ], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "x", + "span": { + "start": 960, + "end": 961 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 963, + "end": 964 + } + }, + "span": { + "start": 960, + "end": 964 + } + } + ], + "span": { + "start": 924, + "end": 970 + } + }, + "span": { + "start": 921, + "end": 970 + } + }, + { + "start": 921, + "end": 970 + } + ], + "span": { + "start": 920, + "end": 970 + } + } + ], + "span": { + "start": 920, + "end": 972 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 903, + "end": 972 + } + }, + { + "type": "Message", + "id": { + "name": "sparse-multiline-call", + "span": { + "start": 972, + "end": 993 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 997, + "end": 1000 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "StringLiteral", + "value": "a", + "span": { + "start": 1016, + "end": 1019 + } + }, + { + "type": "MessageReference", + "id": { + "name": "msg", + "span": { + "start": 1033, + "end": 1036 + } + }, + "attribute": null, + "span": { + "start": 1033, + "end": 1045 + } + } + ], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "x", + "span": { + "start": 1047, + "end": 1048 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 1050, + "end": 1051 + } + }, + "span": { + "start": 1047, + "end": 1051 + } + } + ], + "span": { + "start": 1005, + "end": 1057 + } + }, + "span": { + "start": 997, + "end": 1057 + } + }, + { + "start": 997, + "end": 1057 + } + ], + "span": { + "start": 996, + "end": 1057 + } + } + ], + "span": { + "start": 996, + "end": 1059 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 972, + "end": 1059 + } + }, + { + "type": "Message", + "id": { + "name": "empty-multiline-call", + "span": { + "start": 1059, + "end": 1079 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1083, + "end": 1086 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 1086, + "end": 1094 + } + }, + "span": { + "start": 1083, + "end": 1094 + } + }, + { + "start": 1083, + "end": 1094 + } + ], + "span": { + "start": 1082, + "end": 1094 + } + } + ], + "span": { + "start": 1082, + "end": 1098 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1059, + "end": 1098 + } + }, + { + "type": "Message", + "id": { + "name": "unindented-arg-number", + "span": { + "start": 1098, + "end": 1119 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1123, + "end": 1126 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 1128, + "end": 1129 + } + } + ], + "named": [], + "span": { + "start": 1126, + "end": 1130 + } + }, + "span": { + "start": 1123, + "end": 1130 + } + }, + { + "start": 1123, + "end": 1130 + } + ], + "span": { + "start": 1122, + "end": 1130 + } + } + ], + "span": { + "start": 1122, + "end": 1133 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1098, + "end": 1133 + } + }, + { + "type": "Message", + "id": { + "name": "unindented-arg-string", + "span": { + "start": 1133, + "end": 1154 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1158, + "end": 1161 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "StringLiteral", + "value": "a", + "span": { + "start": 1163, + "end": 1166 + } + } + ], + "named": [], + "span": { + "start": 1161, + "end": 1167 + } + }, + "span": { + "start": 1158, + "end": 1167 + } + }, + { + "start": 1158, + "end": 1167 + } + ], + "span": { + "start": 1157, + "end": 1167 + } + } + ], + "span": { + "start": 1157, + "end": 1170 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1133, + "end": 1170 + } + }, + { + "type": "Message", + "id": { + "name": "unindented-arg-msg-ref", + "span": { + "start": 1170, + "end": 1192 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1196, + "end": 1199 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "MessageReference", + "id": { + "name": "msg", + "span": { + "start": 1201, + "end": 1204 + } + }, + "attribute": null, + "span": { + "start": 1201, + "end": 1204 + } + } + ], + "named": [], + "span": { + "start": 1199, + "end": 1205 + } + }, + "span": { + "start": 1196, + "end": 1205 + } + }, + { + "start": 1196, + "end": 1205 + } + ], + "span": { + "start": 1195, + "end": 1205 + } + } + ], + "span": { + "start": 1195, + "end": 1208 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1170, + "end": 1208 + } + }, + { + "type": "Message", + "id": { + "name": "unindented-arg-term-ref", + "span": { + "start": 1208, + "end": 1231 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1235, + "end": 1238 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "TermReference", + "id": { + "name": "msg", + "span": { + "start": 1241, + "end": 1244 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 1240, + "end": 1244 + } + } + ], + "named": [], + "span": { + "start": 1238, + "end": 1245 + } + }, + "span": { + "start": 1235, + "end": 1245 + } + }, + { + "start": 1235, + "end": 1245 + } + ], + "span": { + "start": 1234, + "end": 1245 + } + } + ], + "span": { + "start": 1234, + "end": 1248 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1208, + "end": 1248 + } + }, + { + "type": "Message", + "id": { + "name": "unindented-arg-var-ref", + "span": { + "start": 1248, + "end": 1270 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1274, + "end": 1277 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "VariableReference", + "id": { + "name": "var", + "span": { + "start": 1280, + "end": 1283 + } + }, + "span": { + "start": 1279, + "end": 1283 + } + } + ], + "named": [], + "span": { + "start": 1277, + "end": 1284 + } + }, + "span": { + "start": 1274, + "end": 1284 + } + }, + { + "start": 1274, + "end": 1284 + } + ], + "span": { + "start": 1273, + "end": 1284 + } + } + ], + "span": { + "start": 1273, + "end": 1287 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1248, + "end": 1287 + } + }, + { + "type": "Message", + "id": { + "name": "unindented-arg-call", + "span": { + "start": 1287, + "end": 1306 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1310, + "end": 1313 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "FunctionReference", + "id": { + "name": "OTHER", + "span": { + "start": 1315, + "end": 1320 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 1320, + "end": 1322 + } + }, + "span": { + "start": 1315, + "end": 1322 + } + } + ], + "named": [], + "span": { + "start": 1313, + "end": 1323 + } + }, + "span": { + "start": 1310, + "end": 1323 + } + }, + { + "start": 1310, + "end": 1323 + } + ], + "span": { + "start": 1309, + "end": 1323 + } + } + ], + "span": { + "start": 1309, + "end": 1326 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1287, + "end": 1326 + } + }, + { + "type": "Message", + "id": { + "name": "unindented-named-arg", + "span": { + "start": 1326, + "end": 1346 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1350, + "end": 1353 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "x", + "span": { + "start": 1355, + "end": 1356 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 1357, + "end": 1358 + } + }, + "span": { + "start": 1355, + "end": 1358 + } + } + ], + "span": { + "start": 1353, + "end": 1359 + } + }, + "span": { + "start": 1350, + "end": 1359 + } + }, + { + "start": 1350, + "end": 1359 + } + ], + "span": { + "start": 1349, + "end": 1359 + } + } + ], + "span": { + "start": 1349, + "end": 1362 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1326, + "end": 1362 + } + }, + { + "type": "Message", + "id": { + "name": "unindented-closing-paren", + "span": { + "start": 1362, + "end": 1386 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1390, + "end": 1393 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "MessageReference", + "id": { + "name": "x", + "span": { + "start": 1399, + "end": 1400 + } + }, + "attribute": null, + "span": { + "start": 1399, + "end": 1401 + } + } + ], + "named": [], + "span": { + "start": 1393, + "end": 1402 + } + }, + "span": { + "start": 1390, + "end": 1402 + } + }, + { + "start": 1390, + "end": 1402 + } + ], + "span": { + "start": 1389, + "end": 1402 + } + } + ], + "span": { + "start": 1389, + "end": 1407 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1362, + "end": 1407 + } + }, + { + "type": "GroupComment", + "content": [ + "Optional trailing comma" + ], + "span": { + "start": 1407, + "end": 1433 + } + }, + { + "type": "Message", + "id": { + "name": "one-argument", + "span": { + "start": 1435, + "end": 1447 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1451, + "end": 1454 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 1455, + "end": 1456 + } + } + ], + "named": [], + "span": { + "start": 1454, + "end": 1458 + } + }, + "span": { + "start": 1451, + "end": 1458 + } + }, + { + "start": 1451, + "end": 1458 + } + ], + "span": { + "start": 1450, + "end": 1458 + } + } + ], + "span": { + "start": 1450, + "end": 1460 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1435, + "end": 1460 + } + }, + { + "type": "Message", + "id": { + "name": "many-arguments", + "span": { + "start": 1460, + "end": 1474 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1478, + "end": 1481 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 1482, + "end": 1483 + } + }, + { + "type": "NumberLiteral", + "value": "2", + "span": { + "start": 1485, + "end": 1486 + } + }, + { + "type": "NumberLiteral", + "value": "3", + "span": { + "start": 1488, + "end": 1489 + } + } + ], + "named": [], + "span": { + "start": 1481, + "end": 1491 + } + }, + "span": { + "start": 1478, + "end": 1491 + } + }, + { + "start": 1478, + "end": 1491 + } + ], + "span": { + "start": 1477, + "end": 1491 + } + } + ], + "span": { + "start": 1477, + "end": 1493 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1460, + "end": 1493 + } + }, + { + "type": "Message", + "id": { + "name": "inline-sparse-args", + "span": { + "start": 1493, + "end": 1511 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1515, + "end": 1518 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 1521, + "end": 1522 + } + }, + { + "type": "NumberLiteral", + "value": "2", + "span": { + "start": 1525, + "end": 1526 + } + }, + { + "type": "NumberLiteral", + "value": "3", + "span": { + "start": 1529, + "end": 1530 + } + } + ], + "named": [], + "span": { + "start": 1518, + "end": 1534 + } + }, + "span": { + "start": 1515, + "end": 1534 + } + }, + { + "start": 1515, + "end": 1534 + } + ], + "span": { + "start": 1514, + "end": 1534 + } + } + ], + "span": { + "start": 1514, + "end": 1536 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1493, + "end": 1536 + } + }, + { + "type": "Message", + "id": { + "name": "mulitline-args", + "span": { + "start": 1536, + "end": 1550 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1554, + "end": 1557 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 1567, + "end": 1568 + } + }, + { + "type": "NumberLiteral", + "value": "2", + "span": { + "start": 1578, + "end": 1579 + } + } + ], + "named": [], + "span": { + "start": 1557, + "end": 1586 + } + }, + "span": { + "start": 1554, + "end": 1586 + } + }, + { + "start": 1554, + "end": 1586 + } + ], + "span": { + "start": 1553, + "end": 1586 + } + } + ], + "span": { + "start": 1553, + "end": 1588 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1536, + "end": 1588 + } + }, + { + "type": "Message", + "id": { + "name": "mulitline-sparse-args", + "span": { + "start": 1588, + "end": 1609 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1613, + "end": 1616 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 1627, + "end": 1628 + } + }, + { + "type": "NumberLiteral", + "value": "2", + "span": { + "start": 1647, + "end": 1648 + } + } + ], + "named": [], + "span": { + "start": 1616, + "end": 1667 + } + }, + "span": { + "start": 1613, + "end": 1667 + } + }, + { + "start": 1613, + "end": 1667 + } + ], + "span": { + "start": 1612, + "end": 1667 + } + } + ], + "span": { + "start": 1612, + "end": 1671 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1588, + "end": 1671 + } + }, + { + "type": "GroupComment", + "content": [ + "Syntax errors for trailing comma" + ], + "span": { + "start": 1671, + "end": 1706 + } + }, + { + "type": "Junk", + "content": "one-argument = {FUN(1,,)}\n", + "span": { + "start": 1708, + "end": 1734 + } + }, + { + "type": "Junk", + "content": "missing-arg = {FUN(,)}\n", + "span": { + "start": 1734, + "end": 1757 + } + }, + { + "type": "Junk", + "content": "missing-sparse-arg = {FUN( , )}\n\n\n", + "span": { + "start": 1757, + "end": 1795 + } + }, + { + "type": "GroupComment", + "content": [ + "Whitespace in named arguments" + ], + "span": { + "start": 1795, + "end": 1827 + } + }, + { + "type": "Message", + "id": { + "name": "sparse-named-arg", + "span": { + "start": 1829, + "end": 1845 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1849, + "end": 1852 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "x", + "span": { + "start": 1862, + "end": 1863 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 1870, + "end": 1871 + } + }, + "span": { + "start": 1862, + "end": 1871 + } + }, + { + "type": "NamedArgument", + "name": { + "name": "y", + "span": { + "start": 1881, + "end": 1882 + } + }, + "value": { + "type": "NumberLiteral", + "value": "2", + "span": { + "start": 1889, + "end": 1890 + } + }, + "span": { + "start": 1881, + "end": 1890 + } + }, + { + "type": "NamedArgument", + "name": { + "name": "z", + "span": { + "start": 1900, + "end": 1901 + } + }, + "value": { + "type": "NumberLiteral", + "value": "3", + "span": { + "start": 1920, + "end": 1921 + } + }, + "span": { + "start": 1900, + "end": 1921 + } + } + ], + "span": { + "start": 1852, + "end": 1927 + } + }, + "span": { + "start": 1849, + "end": 1927 + } + }, + { + "start": 1849, + "end": 1927 + } + ], + "span": { + "start": 1848, + "end": 1927 + } + } + ], + "span": { + "start": 1848, + "end": 1931 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1829, + "end": 1931 + } + }, + { + "type": "Message", + "id": { + "name": "unindented-colon", + "span": { + "start": 1931, + "end": 1947 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1951, + "end": 1954 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "x", + "span": { + "start": 1964, + "end": 1965 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 1967, + "end": 1968 + } + }, + "span": { + "start": 1964, + "end": 1968 + } + } + ], + "span": { + "start": 1954, + "end": 1969 + } + }, + "span": { + "start": 1951, + "end": 1969 + } + }, + { + "start": 1951, + "end": 1969 + } + ], + "span": { + "start": 1950, + "end": 1969 + } + } + ], + "span": { + "start": 1950, + "end": 1972 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1931, + "end": 1972 + } + }, + { + "type": "Message", + "id": { + "name": "unindented-value", + "span": { + "start": 1972, + "end": 1988 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUN", + "span": { + "start": 1992, + "end": 1995 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "x", + "span": { + "start": 2005, + "end": 2006 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 2008, + "end": 2009 + } + }, + "span": { + "start": 2005, + "end": 2009 + } + } + ], + "span": { + "start": 1995, + "end": 2010 + } + }, + "span": { + "start": 1992, + "end": 2010 + } + }, + { + "start": 1992, + "end": 2010 + } + ], + "span": { + "start": 1991, + "end": 2010 + } + } + ], + "span": { + "start": 1991, + "end": 2012 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1972, + "end": 2012 + } + } + ], + "span": { + "start": 0, + "end": 2012 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/callee_expressions.spans.json b/fluent-syntax/tests/fixtures/callee_expressions.spans.json new file mode 100644 index 00000000..76e02427 --- /dev/null +++ b/fluent-syntax/tests/fixtures/callee_expressions.spans.json @@ -0,0 +1,524 @@ +{ + "body": [ + { + "type": "GroupComment", + "content": [ + "Callees in placeables." + ], + "span": { + "start": 0, + "end": 25 + } + }, + { + "type": "Message", + "id": { + "name": "function-callee-placeable", + "span": { + "start": 27, + "end": 52 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "FunctionReference", + "id": { + "name": "FUNCTION", + "span": { + "start": 56, + "end": 64 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 64, + "end": 66 + } + }, + "span": { + "start": 56, + "end": 66 + } + }, + { + "start": 56, + "end": 66 + } + ], + "span": { + "start": 55, + "end": 66 + } + } + ], + "span": { + "start": 55, + "end": 68 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 27, + "end": 68 + } + }, + { + "type": "Message", + "id": { + "name": "term-callee-placeable", + "span": { + "start": 68, + "end": 89 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "term", + "span": { + "start": 94, + "end": 98 + } + }, + "attribute": null, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 98, + "end": 100 + } + }, + "span": { + "start": 93, + "end": 100 + } + }, + { + "start": 93, + "end": 100 + } + ], + "span": { + "start": 92, + "end": 100 + } + } + ], + "span": { + "start": 92, + "end": 103 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 68, + "end": 103 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Messages cannot be parameterized." + ], + "span": { + "start": 103, + "end": 144 + } + }, + { + "type": "Junk", + "content": "message-callee-placeable = {message()}\n", + "span": { + "start": 145, + "end": 184 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Equivalent to a MessageReference callee." + ], + "span": { + "start": 184, + "end": 232 + } + }, + { + "type": "Junk", + "content": "mixed-case-callee-placeable = {Function()}\n", + "span": { + "start": 233, + "end": 276 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Message attributes cannot be parameterized." + ], + "span": { + "start": 276, + "end": 327 + } + }, + { + "type": "Junk", + "content": "message-attr-callee-placeable = {message.attr()}\n", + "span": { + "start": 328, + "end": 377 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Term attributes may not be used in Placeables." + ], + "span": { + "start": 377, + "end": 431 + } + }, + { + "type": "Junk", + "content": "term-attr-callee-placeable = {-term.attr()}\n", + "span": { + "start": 432, + "end": 476 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Variables cannot be parameterized." + ], + "span": { + "start": 476, + "end": 518 + } + }, + { + "type": "Junk", + "content": "variable-callee-placeable = {$variable()}\n\n\n", + "span": { + "start": 519, + "end": 563 + } + }, + { + "type": "GroupComment", + "content": [ + "Callees in selectors." + ], + "span": { + "start": 563, + "end": 587 + } + }, + { + "type": "Message", + "id": { + "name": "function-callee-selector", + "span": { + "start": 589, + "end": 613 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "FUNCTION", + "span": { + "start": 617, + "end": 625 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 625, + "end": 627 + } + }, + "span": { + "start": 617, + "end": 627 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 636, + "end": 639 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 641, + "end": 647 + } + } + ], + "span": { + "start": 641, + "end": 647 + } + }, + "default": true, + "span": { + "start": 634, + "end": 647 + } + } + ], + "span": { + "start": 617, + "end": 647 + } + }, + "span": { + "start": 616, + "end": 647 + } + } + ], + "span": { + "start": 616, + "end": 649 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 589, + "end": 649 + } + }, + { + "type": "Message", + "id": { + "name": "term-attr-callee-selector", + "span": { + "start": 649, + "end": 674 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "TermReference", + "id": { + "name": "term", + "span": { + "start": 679, + "end": 683 + } + }, + "attribute": { + "name": "attr", + "span": { + "start": 684, + "end": 688 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 688, + "end": 690 + } + }, + "span": { + "start": 678, + "end": 690 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 699, + "end": 702 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 704, + "end": 710 + } + } + ], + "span": { + "start": 704, + "end": 710 + } + }, + "default": true, + "span": { + "start": 697, + "end": 710 + } + } + ], + "span": { + "start": 678, + "end": 710 + } + }, + "span": { + "start": 677, + "end": 710 + } + } + ], + "span": { + "start": 677, + "end": 713 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 649, + "end": 713 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Messages cannot be parameterized." + ], + "span": { + "start": 713, + "end": 754 + } + }, + { + "type": "Junk", + "content": "message-callee-selector = {message() ->\n *[key] Value\n}\n", + "span": { + "start": 755, + "end": 813 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Equivalent to a MessageReference callee." + ], + "span": { + "start": 813, + "end": 861 + } + }, + { + "type": "Junk", + "content": "mixed-case-callee-selector = {Function() ->\n *[key] Value\n}\n", + "span": { + "start": 862, + "end": 924 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Message attributes cannot be parameterized." + ], + "span": { + "start": 924, + "end": 975 + } + }, + { + "type": "Junk", + "content": "message-attr-callee-selector = {message.attr() ->\n *[key] Value\n}\n", + "span": { + "start": 976, + "end": 1044 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Term values may not be used as selectors." + ], + "span": { + "start": 1044, + "end": 1093 + } + }, + { + "type": "Junk", + "content": "term-callee-selector = {-term() ->\n *[key] Value\n}\n", + "span": { + "start": 1094, + "end": 1147 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Variables cannot be parameterized." + ], + "span": { + "start": 1147, + "end": 1189 + } + }, + { + "type": "Junk", + "content": "variable-callee-selector = {$variable() ->\n *[key] Value\n}\n", + "span": { + "start": 1190, + "end": 1251 + } + } + ], + "span": { + "start": 0, + "end": 1251 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/comments.spans.json b/fluent-syntax/tests/fixtures/comments.spans.json new file mode 100644 index 00000000..6994c83d --- /dev/null +++ b/fluent-syntax/tests/fixtures/comments.spans.json @@ -0,0 +1,166 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "Standalone Comment" + ], + "span": { + "start": 0, + "end": 20 + } + }, + { + "type": "Message", + "id": { + "name": "foo", + "span": { + "start": 40, + "end": 43 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Foo", + "span": { + "start": 46, + "end": 50 + } + } + ], + "span": { + "start": 46, + "end": 51 + } + }, + "attributes": [], + "comment": { + "content": [ + "Message Comment" + ], + "span": { + "start": 22, + "end": 39 + } + }, + "span": { + "start": 40, + "end": 51 + } + }, + { + "type": "Term", + "id": { + "name": "term", + "span": { + "start": 95, + "end": 99 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Term", + "span": { + "start": 102, + "end": 107 + } + } + ], + "span": { + "start": 102, + "end": 108 + } + }, + "attributes": [], + "comment": { + "content": [ + "Term Comment", + "with a blank last line.", + "" + ], + "span": { + "start": 51, + "end": 93 + } + }, + "span": { + "start": 94, + "end": 108 + } + }, + { + "type": "Comment", + "content": [ + "Another standalone", + "", + " with indent" + ], + "span": { + "start": 108, + "end": 151 + } + }, + { + "type": "GroupComment", + "content": [ + "Group Comment" + ], + "span": { + "start": 151, + "end": 168 + } + }, + { + "type": "ResourceComment", + "content": [ + "Resource Comment" + ], + "span": { + "start": 168, + "end": 188 + } + }, + { + "type": "Comment", + "content": [ + "Errors" + ], + "span": { + "start": 190, + "end": 199 + } + }, + { + "type": "Junk", + "content": "#error\n", + "span": { + "start": 199, + "end": 206 + } + }, + { + "type": "Junk", + "content": "##error\n", + "span": { + "start": 206, + "end": 214 + } + }, + { + "type": "Junk", + "content": "###error\n", + "span": { + "start": 214, + "end": 223 + } + } + ], + "span": { + "start": 0, + "end": 223 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/cr.spans.json b/fluent-syntax/tests/fixtures/cr.spans.json new file mode 100644 index 00000000..3dd18022 --- /dev/null +++ b/fluent-syntax/tests/fixtures/cr.spans.json @@ -0,0 +1,18 @@ +{ + "body": [ + { + "type": "ResourceComment", + "content": [ + "This entire file uses CR as EOL.\r\rerr01 = Value 01\rerr02 = Value 02\r\rerr03 =\r\r Value 03\r Continued\r\r .title = Title\r\rerr04 = { \"str\r\rerr05 = { $sel -> }\r" + ], + "span": { + "start": 0, + "end": 166 + } + } + ], + "span": { + "start": 0, + "end": 166 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/crlf.spans.json b/fluent-syntax/tests/fixtures/crlf.spans.json new file mode 100644 index 00000000..f6798b1d --- /dev/null +++ b/fluent-syntax/tests/fixtures/crlf.spans.json @@ -0,0 +1,164 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "key01", + "span": { + "start": 48, + "end": 53 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value 01", + "span": { + "start": 56, + "end": 64 + } + } + ], + "span": { + "start": 56, + "end": 66 + } + }, + "attributes": [], + "comment": { + "content": [ + "Term Comment", + "with a blank last line.", + "" + ], + "span": { + "start": 2, + "end": 47 + } + }, + "span": { + "start": 48, + "end": 66 + } + }, + { + "type": "Message", + "id": { + "name": "key02", + "span": { + "start": 66, + "end": 71 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value 02", + "span": { + "start": 81, + "end": 89 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 90, + "end": 91 + } + }, + { + "type": "TextElement", + "value": "Continued", + "span": { + "start": 95, + "end": 104 + } + } + ], + "span": { + "start": 73, + "end": 108 + } + }, + "attributes": [ + { + "id": { + "name": "title", + "span": { + "start": 113, + "end": 118 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Title", + "span": { + "start": 121, + "end": 126 + } + } + ], + "span": { + "start": 121, + "end": 130 + } + }, + "span": { + "start": 129, + "end": 130 + } + } + ], + "comment": null, + "span": { + "start": 66, + "end": 130 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Unclosed StringLiteral" + ], + "span": { + "start": 130, + "end": 161 + } + }, + { + "type": "Junk", + "content": "err03 = { \"str\r\n\r\n", + "span": { + "start": 162, + "end": 180 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Missing newline after ->." + ], + "span": { + "start": 180, + "end": 214 + } + }, + { + "type": "Junk", + "content": "err04 = { $sel -> }\r\n", + "span": { + "start": 215, + "end": 236 + } + } + ], + "span": { + "start": 0, + "end": 236 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/eof_comment.spans.json b/fluent-syntax/tests/fixtures/eof_comment.spans.json new file mode 100644 index 00000000..cf011c80 --- /dev/null +++ b/fluent-syntax/tests/fixtures/eof_comment.spans.json @@ -0,0 +1,28 @@ +{ + "body": [ + { + "type": "ResourceComment", + "content": [ + "NOTE: Disable final newline insertion when editing this file." + ], + "span": { + "start": 0, + "end": 65 + } + }, + { + "type": "Comment", + "content": [ + "No EOL" + ], + "span": { + "start": 67, + "end": 75 + } + } + ], + "span": { + "start": 0, + "end": 75 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/eof_empty.spans.json b/fluent-syntax/tests/fixtures/eof_empty.spans.json new file mode 100644 index 00000000..80b9c4ce --- /dev/null +++ b/fluent-syntax/tests/fixtures/eof_empty.spans.json @@ -0,0 +1,7 @@ +{ + "body": [], + "span": { + "start": 0, + "end": 0 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/eof_id.spans.json b/fluent-syntax/tests/fixtures/eof_id.spans.json new file mode 100644 index 00000000..954d752b --- /dev/null +++ b/fluent-syntax/tests/fixtures/eof_id.spans.json @@ -0,0 +1,26 @@ +{ + "body": [ + { + "type": "ResourceComment", + "content": [ + "NOTE: Disable final newline insertion when editing this file." + ], + "span": { + "start": 0, + "end": 65 + } + }, + { + "type": "Junk", + "content": "message-id", + "span": { + "start": 67, + "end": 77 + } + } + ], + "span": { + "start": 0, + "end": 77 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/eof_id_equals.spans.json b/fluent-syntax/tests/fixtures/eof_id_equals.spans.json new file mode 100644 index 00000000..fc3d18d2 --- /dev/null +++ b/fluent-syntax/tests/fixtures/eof_id_equals.spans.json @@ -0,0 +1,26 @@ +{ + "body": [ + { + "type": "ResourceComment", + "content": [ + "NOTE: Disable final newline insertion when editing this file." + ], + "span": { + "start": 0, + "end": 65 + } + }, + { + "type": "Junk", + "content": "message-id =", + "span": { + "start": 67, + "end": 79 + } + } + ], + "span": { + "start": 0, + "end": 79 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/eof_junk.spans.json b/fluent-syntax/tests/fixtures/eof_junk.spans.json new file mode 100644 index 00000000..446fc329 --- /dev/null +++ b/fluent-syntax/tests/fixtures/eof_junk.spans.json @@ -0,0 +1,26 @@ +{ + "body": [ + { + "type": "ResourceComment", + "content": [ + "NOTE: Disable final newline insertion when editing this file." + ], + "span": { + "start": 0, + "end": 65 + } + }, + { + "type": "Junk", + "content": "000", + "span": { + "start": 67, + "end": 70 + } + } + ], + "span": { + "start": 0, + "end": 70 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/eof_value.spans.json b/fluent-syntax/tests/fixtures/eof_value.spans.json new file mode 100644 index 00000000..fd9aa20d --- /dev/null +++ b/fluent-syntax/tests/fixtures/eof_value.spans.json @@ -0,0 +1,50 @@ +{ + "body": [ + { + "type": "ResourceComment", + "content": [ + "NOTE: Disable final newline insertion when editing this file." + ], + "span": { + "start": 0, + "end": 65 + } + }, + { + "type": "Message", + "id": { + "name": "no-eol", + "span": { + "start": 67, + "end": 73 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "No EOL", + "span": { + "start": 76, + "end": 82 + } + } + ], + "span": { + "start": 76, + "end": 82 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 67, + "end": 82 + } + } + ], + "span": { + "start": 0, + "end": 82 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/escaped_characters.spans.json b/fluent-syntax/tests/fixtures/escaped_characters.spans.json new file mode 100644 index 00000000..88b3524e --- /dev/null +++ b/fluent-syntax/tests/fixtures/escaped_characters.spans.json @@ -0,0 +1,824 @@ +{ + "body": [ + { + "type": "GroupComment", + "content": [ + "Literal text" + ], + "span": { + "start": 0, + "end": 15 + } + }, + { + "type": "Message", + "id": { + "name": "text-backslash-one", + "span": { + "start": 16, + "end": 34 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value with \\ a backslash", + "span": { + "start": 37, + "end": 62 + } + } + ], + "span": { + "start": 37, + "end": 62 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 16, + "end": 62 + } + }, + { + "type": "Message", + "id": { + "name": "text-backslash-two", + "span": { + "start": 62, + "end": 80 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value with \\\\ two backslashes", + "span": { + "start": 83, + "end": 113 + } + } + ], + "span": { + "start": 83, + "end": 113 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 62, + "end": 113 + } + }, + { + "type": "Message", + "id": { + "name": "text-backslash-brace", + "span": { + "start": 113, + "end": 133 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value with \\", + "span": { + "start": 136, + "end": 148 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "placeable", + "span": { + "start": 149, + "end": 158 + } + }, + "attribute": null, + "span": { + "start": 149, + "end": 158 + } + }, + { + "start": 149, + "end": 158 + } + ], + "span": { + "start": 148, + "end": 158 + } + } + ], + "span": { + "start": 136, + "end": 160 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 113, + "end": 160 + } + }, + { + "type": "Message", + "id": { + "name": "text-backslash-u", + "span": { + "start": 160, + "end": 176 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "\\u0041", + "span": { + "start": 179, + "end": 186 + } + } + ], + "span": { + "start": 179, + "end": 186 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 160, + "end": 186 + } + }, + { + "type": "Message", + "id": { + "name": "text-backslash-backslash-u", + "span": { + "start": 186, + "end": 212 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "\\\\u0041", + "span": { + "start": 215, + "end": 223 + } + } + ], + "span": { + "start": 215, + "end": 224 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 186, + "end": 224 + } + }, + { + "type": "GroupComment", + "content": [ + "String literals" + ], + "span": { + "start": 224, + "end": 242 + } + }, + { + "type": "Message", + "id": { + "name": "quote-in-string", + "span": { + "start": 243, + "end": 258 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\\"", + "span": { + "start": 262, + "end": 266 + } + }, + { + "start": 262, + "end": 266 + } + ], + "span": { + "start": 261, + "end": 266 + } + } + ], + "span": { + "start": 261, + "end": 268 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 243, + "end": 268 + } + }, + { + "type": "Message", + "id": { + "name": "backslash-in-string", + "span": { + "start": 268, + "end": 287 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\\\", + "span": { + "start": 291, + "end": 295 + } + }, + { + "start": 291, + "end": 295 + } + ], + "span": { + "start": 290, + "end": 295 + } + } + ], + "span": { + "start": 290, + "end": 297 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 268, + "end": 297 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Mismatched quote" + ], + "span": { + "start": 297, + "end": 321 + } + }, + { + "type": "Junk", + "content": "mismatched-quote = {\"\\\\\"\"}\n", + "span": { + "start": 322, + "end": 349 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Unknown escape" + ], + "span": { + "start": 349, + "end": 371 + } + }, + { + "type": "Junk", + "content": "unknown-escape = {\"\\x\"}\n", + "span": { + "start": 372, + "end": 396 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Multiline literal" + ], + "span": { + "start": 396, + "end": 421 + } + }, + { + "type": "Junk", + "content": "invalid-multiline-literal = {\"\n \"}\n\n", + "span": { + "start": 422, + "end": 458 + } + }, + { + "type": "GroupComment", + "content": [ + "Unicode escapes" + ], + "span": { + "start": 458, + "end": 476 + } + }, + { + "type": "Message", + "id": { + "name": "string-unicode-4digits", + "span": { + "start": 477, + "end": 499 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\u0041", + "span": { + "start": 503, + "end": 511 + } + }, + { + "start": 503, + "end": 511 + } + ], + "span": { + "start": 502, + "end": 511 + } + } + ], + "span": { + "start": 502, + "end": 513 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 477, + "end": 513 + } + }, + { + "type": "Message", + "id": { + "name": "escape-unicode-4digits", + "span": { + "start": 513, + "end": 535 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\\\u0041", + "span": { + "start": 539, + "end": 548 + } + }, + { + "start": 539, + "end": 548 + } + ], + "span": { + "start": 538, + "end": 548 + } + } + ], + "span": { + "start": 538, + "end": 550 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 513, + "end": 550 + } + }, + { + "type": "Message", + "id": { + "name": "string-unicode-6digits", + "span": { + "start": 550, + "end": 572 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\U01F602", + "span": { + "start": 576, + "end": 586 + } + }, + { + "start": 576, + "end": 586 + } + ], + "span": { + "start": 575, + "end": 586 + } + } + ], + "span": { + "start": 575, + "end": 588 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 550, + "end": 588 + } + }, + { + "type": "Message", + "id": { + "name": "escape-unicode-6digits", + "span": { + "start": 588, + "end": 610 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\\\U01F602", + "span": { + "start": 614, + "end": 625 + } + }, + { + "start": 614, + "end": 625 + } + ], + "span": { + "start": 613, + "end": 625 + } + } + ], + "span": { + "start": 613, + "end": 628 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 588, + "end": 628 + } + }, + { + "type": "Message", + "id": { + "name": "string-too-many-4digits", + "span": { + "start": 681, + "end": 704 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\u004100", + "span": { + "start": 708, + "end": 718 + } + }, + { + "start": 708, + "end": 718 + } + ], + "span": { + "start": 707, + "end": 718 + } + } + ], + "span": { + "start": 707, + "end": 720 + } + }, + "attributes": [], + "comment": { + "content": [ + "OK The trailing \"00\" is part of the literal value." + ], + "span": { + "start": 628, + "end": 680 + } + }, + "span": { + "start": 681, + "end": 720 + } + }, + { + "type": "Message", + "id": { + "name": "string-too-many-6digits", + "span": { + "start": 773, + "end": 796 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "\\U01F60200", + "span": { + "start": 800, + "end": 812 + } + }, + { + "start": 800, + "end": 812 + } + ], + "span": { + "start": 799, + "end": 812 + } + } + ], + "span": { + "start": 799, + "end": 815 + } + }, + "attributes": [], + "comment": { + "content": [ + "OK The trailing \"00\" is part of the literal value." + ], + "span": { + "start": 720, + "end": 772 + } + }, + "span": { + "start": 773, + "end": 815 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Too few hex digits after \\u." + ], + "span": { + "start": 815, + "end": 851 + } + }, + { + "type": "Junk", + "content": "string-too-few-4digits = {\"\\u41\"}\n", + "span": { + "start": 852, + "end": 886 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Too few hex digits after \\U." + ], + "span": { + "start": 886, + "end": 922 + } + }, + { + "type": "Junk", + "content": "string-too-few-6digits = {\"\\U1F602\"}\n\n", + "span": { + "start": 923, + "end": 961 + } + }, + { + "type": "GroupComment", + "content": [ + "Literal braces" + ], + "span": { + "start": 961, + "end": 978 + } + }, + { + "type": "Message", + "id": { + "name": "brace-open", + "span": { + "start": 979, + "end": 989 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "An opening ", + "span": { + "start": 992, + "end": 1003 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "{", + "span": { + "start": 1004, + "end": 1007 + } + }, + { + "start": 1004, + "end": 1007 + } + ], + "span": { + "start": 1003, + "end": 1007 + } + }, + { + "type": "TextElement", + "value": " brace.", + "span": { + "start": 1008, + "end": 1016 + } + } + ], + "span": { + "start": 992, + "end": 1016 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 979, + "end": 1016 + } + }, + { + "type": "Message", + "id": { + "name": "brace-close", + "span": { + "start": 1016, + "end": 1027 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A closing ", + "span": { + "start": 1030, + "end": 1040 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "}", + "span": { + "start": 1041, + "end": 1044 + } + }, + { + "start": 1041, + "end": 1044 + } + ], + "span": { + "start": 1040, + "end": 1044 + } + }, + { + "type": "TextElement", + "value": " brace.", + "span": { + "start": 1045, + "end": 1053 + } + } + ], + "span": { + "start": 1030, + "end": 1053 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1016, + "end": 1053 + } + } + ], + "span": { + "start": 0, + "end": 1053 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/junk.spans.json b/fluent-syntax/tests/fixtures/junk.spans.json new file mode 100644 index 00000000..12820fc9 --- /dev/null +++ b/fluent-syntax/tests/fixtures/junk.spans.json @@ -0,0 +1,135 @@ +{ + "body": [ + { + "type": "GroupComment", + "content": [ + "Two adjacent Junks." + ], + "span": { + "start": 0, + "end": 22 + } + }, + { + "type": "Junk", + "content": "err01 = {1x}\n", + "span": { + "start": 23, + "end": 36 + } + }, + { + "type": "Junk", + "content": "err02 = {2x}\n\n", + "span": { + "start": 36, + "end": 50 + } + }, + { + "type": "Comment", + "content": [ + "A single Junk." + ], + "span": { + "start": 50, + "end": 66 + } + }, + { + "type": "Junk", + "content": "err03 = {1x\n2\n\n", + "span": { + "start": 67, + "end": 82 + } + }, + { + "type": "Comment", + "content": [ + "A single Junk." + ], + "span": { + "start": 82, + "end": 98 + } + }, + { + "type": "Junk", + "content": "ą=Invalid identifier\nć=Another one\n\n", + "span": { + "start": 99, + "end": 137 + } + }, + { + "type": "Comment", + "content": [ + "The COMMENT ends this junk." + ], + "span": { + "start": 137, + "end": 166 + } + }, + { + "type": "Junk", + "content": "err04 = {\n", + "span": { + "start": 167, + "end": 177 + } + }, + { + "type": "Comment", + "content": [ + "COMMENT" + ], + "span": { + "start": 177, + "end": 186 + } + }, + { + "type": "Comment", + "content": [ + "The COMMENT ends this junk.", + "The closing brace is a separate Junk." + ], + "span": { + "start": 188, + "end": 257 + } + }, + { + "type": "Junk", + "content": "err04 = {\n", + "span": { + "start": 258, + "end": 268 + } + }, + { + "type": "Comment", + "content": [ + "COMMENT" + ], + "span": { + "start": 268, + "end": 277 + } + }, + { + "type": "Junk", + "content": "}\n", + "span": { + "start": 278, + "end": 280 + } + } + ], + "span": { + "start": 0, + "end": 280 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/leading_dots.spans.json b/fluent-syntax/tests/fixtures/leading_dots.spans.json new file mode 100644 index 00000000..d2261fb8 --- /dev/null +++ b/fluent-syntax/tests/fixtures/leading_dots.spans.json @@ -0,0 +1,957 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "key01", + "span": { + "start": 0, + "end": 5 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": ".Value", + "span": { + "start": 8, + "end": 15 + } + } + ], + "span": { + "start": 8, + "end": 15 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 15 + } + }, + { + "type": "Message", + "id": { + "name": "key02", + "span": { + "start": 15, + "end": 20 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "…Value", + "span": { + "start": 23, + "end": 32 + } + } + ], + "span": { + "start": 23, + "end": 32 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 15, + "end": 32 + } + }, + { + "type": "Message", + "id": { + "name": "key03", + "span": { + "start": 32, + "end": 37 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 41, + "end": 44 + } + }, + { + "start": 41, + "end": 44 + } + ], + "span": { + "start": 40, + "end": 44 + } + }, + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 45, + "end": 51 + } + } + ], + "span": { + "start": 40, + "end": 51 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 32, + "end": 51 + } + }, + { + "type": "Message", + "id": { + "name": "key04", + "span": { + "start": 51, + "end": 56 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 64, + "end": 67 + } + }, + { + "start": 64, + "end": 67 + } + ], + "span": { + "start": 63, + "end": 67 + } + }, + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 68, + "end": 74 + } + } + ], + "span": { + "start": 58, + "end": 75 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 51, + "end": 75 + } + }, + { + "type": "Message", + "id": { + "name": "key05", + "span": { + "start": 75, + "end": 80 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value\n", + "span": { + "start": 83, + "end": 89 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 94, + "end": 97 + } + }, + { + "start": 94, + "end": 97 + } + ], + "span": { + "start": 93, + "end": 97 + } + }, + { + "type": "TextElement", + "value": "Continued", + "span": { + "start": 98, + "end": 108 + } + } + ], + "span": { + "start": 83, + "end": 109 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 75, + "end": 109 + } + }, + { + "type": "Message", + "id": { + "name": "key06", + "span": { + "start": 109, + "end": 114 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": ".Value\n", + "span": { + "start": 117, + "end": 124 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 129, + "end": 132 + } + }, + { + "start": 129, + "end": 132 + } + ], + "span": { + "start": 128, + "end": 132 + } + }, + { + "type": "TextElement", + "value": "Continued", + "span": { + "start": 133, + "end": 143 + } + } + ], + "span": { + "start": 117, + "end": 144 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 109, + "end": 144 + } + }, + { + "type": "Message", + "id": { + "name": "key07", + "span": { + "start": 233, + "end": 238 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 241, + "end": 247 + } + } + ], + "span": { + "start": 241, + "end": 247 + } + }, + "attributes": [], + "comment": { + "content": [ + "MESSAGE (value = \"Value\", attributes = [])", + "JUNK (attr .Continued\" must have a value)" + ], + "span": { + "start": 144, + "end": 232 + } + }, + "span": { + "start": 233, + "end": 247 + } + }, + { + "type": "Junk", + "content": " .Continued\n\n", + "span": { + "start": 247, + "end": 263 + } + }, + { + "type": "Comment", + "content": [ + "JUNK (attr .Value must have a value)" + ], + "span": { + "start": 263, + "end": 301 + } + }, + { + "type": "Junk", + "content": "key08 =\n .Value\n\n", + "span": { + "start": 302, + "end": 322 + } + }, + { + "type": "Comment", + "content": [ + "JUNK (attr .Value must have a value)" + ], + "span": { + "start": 322, + "end": 360 + } + }, + { + "type": "Junk", + "content": "key09 =\n .Value\n Continued\n\n", + "span": { + "start": 361, + "end": 395 + } + }, + { + "type": "Message", + "id": { + "name": "key10", + "span": { + "start": 395, + "end": 400 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "Value", + "span": { + "start": 408, + "end": 413 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "which is an attribute\n", + "span": { + "start": 416, + "end": 438 + } + }, + { + "type": "TextElement", + "value": "Continued", + "span": { + "start": 442, + "end": 452 + } + } + ], + "span": { + "start": 416, + "end": 453 + } + }, + "span": { + "start": 452, + "end": 453 + } + } + ], + "comment": null, + "span": { + "start": 395, + "end": 453 + } + }, + { + "type": "Message", + "id": { + "name": "key11", + "span": { + "start": 453, + "end": 458 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 466, + "end": 469 + } + }, + { + "start": 466, + "end": 469 + } + ], + "span": { + "start": 465, + "end": 469 + } + }, + { + "type": "TextElement", + "value": "Value = which looks like an attribute\n", + "span": { + "start": 470, + "end": 508 + } + }, + { + "type": "TextElement", + "value": "Continued", + "span": { + "start": 512, + "end": 522 + } + } + ], + "span": { + "start": 460, + "end": 523 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 453, + "end": 523 + } + }, + { + "type": "Message", + "id": { + "name": "key12", + "span": { + "start": 523, + "end": 528 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "accesskey", + "span": { + "start": 536, + "end": 545 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A", + "span": { + "start": 552, + "end": 554 + } + } + ], + "span": { + "start": 547, + "end": 555 + } + }, + "span": { + "start": 554, + "end": 555 + } + } + ], + "comment": null, + "span": { + "start": 523, + "end": 555 + } + }, + { + "type": "Message", + "id": { + "name": "key13", + "span": { + "start": 555, + "end": 560 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attribute", + "span": { + "start": 568, + "end": 577 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": ".Value", + "span": { + "start": 580, + "end": 587 + } + } + ], + "span": { + "start": 580, + "end": 588 + } + }, + "span": { + "start": 587, + "end": 588 + } + } + ], + "comment": null, + "span": { + "start": 555, + "end": 588 + } + }, + { + "type": "Message", + "id": { + "name": "key14", + "span": { + "start": 588, + "end": 593 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attribute", + "span": { + "start": 601, + "end": 610 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 623, + "end": 626 + } + }, + { + "start": 623, + "end": 626 + } + ], + "span": { + "start": 622, + "end": 626 + } + }, + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 627, + "end": 633 + } + } + ], + "span": { + "start": 612, + "end": 634 + } + }, + "span": { + "start": 633, + "end": 634 + } + } + ], + "comment": null, + "span": { + "start": 588, + "end": 634 + } + }, + { + "type": "Message", + "id": { + "name": "key15", + "span": { + "start": 634, + "end": 639 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 648, + "end": 649 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "one", + "span": { + "start": 662, + "end": 665 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": ".Value", + "span": { + "start": 667, + "end": 674 + } + } + ], + "span": { + "start": 667, + "end": 674 + } + }, + "default": false, + "span": { + "start": 661, + "end": 674 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 683, + "end": 688 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 703, + "end": 706 + } + }, + { + "start": 703, + "end": 706 + } + ], + "span": { + "start": 702, + "end": 706 + } + }, + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 707, + "end": 713 + } + } + ], + "span": { + "start": 689, + "end": 713 + } + }, + "default": true, + "span": { + "start": 681, + "end": 713 + } + } + ], + "span": { + "start": 648, + "end": 717 + } + }, + "span": { + "start": 646, + "end": 717 + } + } + ], + "span": { + "start": 641, + "end": 720 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 634, + "end": 720 + } + }, + { + "type": "Comment", + "content": [ + "JUNK (variant must have a value)" + ], + "span": { + "start": 720, + "end": 754 + } + }, + { + "type": "Junk", + "content": "key16 =\n { 1 ->\n *[one]\n .Value\n }\n\n", + "span": { + "start": 755, + "end": 813 + } + }, + { + "type": "Comment", + "content": [ + "JUNK (unclosed placeable)" + ], + "span": { + "start": 813, + "end": 840 + } + }, + { + "type": "Junk", + "content": "key17 =\n { 1 ->\n *[one] Value\n .Continued\n }\n\n", + "span": { + "start": 841, + "end": 909 + } + }, + { + "type": "Comment", + "content": [ + "JUNK (attr .Value must have a value)" + ], + "span": { + "start": 909, + "end": 947 + } + }, + { + "type": "Junk", + "content": "key18 =\n.Value\n\n", + "span": { + "start": 948, + "end": 964 + } + }, + { + "type": "Message", + "id": { + "name": "key19", + "span": { + "start": 964, + "end": 969 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attribute", + "span": { + "start": 973, + "end": 982 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value\n", + "span": { + "start": 985, + "end": 991 + } + }, + { + "type": "TextElement", + "value": "Continued", + "span": { + "start": 995, + "end": 1005 + } + } + ], + "span": { + "start": 985, + "end": 1006 + } + }, + "span": { + "start": 1005, + "end": 1006 + } + } + ], + "comment": null, + "span": { + "start": 964, + "end": 1006 + } + }, + { + "type": "Message", + "id": { + "name": "key20", + "span": { + "start": 1006, + "end": 1011 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 1015, + "end": 1018 + } + }, + { + "start": 1015, + "end": 1018 + } + ], + "span": { + "start": 1014, + "end": 1018 + } + }, + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 1019, + "end": 1025 + } + } + ], + "span": { + "start": 1013, + "end": 1025 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1006, + "end": 1025 + } + } + ], + "span": { + "start": 0, + "end": 1025 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/literal_expressions.spans.json b/fluent-syntax/tests/fixtures/literal_expressions.spans.json new file mode 100644 index 00000000..6bdc98f9 --- /dev/null +++ b/fluent-syntax/tests/fixtures/literal_expressions.spans.json @@ -0,0 +1,143 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "string-expression", + "span": { + "start": 0, + "end": 17 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "abc", + "span": { + "start": 21, + "end": 26 + } + }, + { + "start": 21, + "end": 26 + } + ], + "span": { + "start": 20, + "end": 26 + } + } + ], + "span": { + "start": 20, + "end": 28 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 28 + } + }, + { + "type": "Message", + "id": { + "name": "number-expression", + "span": { + "start": 28, + "end": 45 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "123", + "span": { + "start": 49, + "end": 52 + } + }, + { + "start": 49, + "end": 52 + } + ], + "span": { + "start": 48, + "end": 52 + } + } + ], + "span": { + "start": 48, + "end": 54 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 28, + "end": 54 + } + }, + { + "type": "Message", + "id": { + "name": "number-expression", + "span": { + "start": 54, + "end": 71 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-3.14", + "span": { + "start": 75, + "end": 80 + } + }, + { + "start": 75, + "end": 80 + } + ], + "span": { + "start": 74, + "end": 80 + } + } + ], + "span": { + "start": 74, + "end": 82 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 54, + "end": 82 + } + } + ], + "span": { + "start": 0, + "end": 82 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/member_expressions.spans.json b/fluent-syntax/tests/fixtures/member_expressions.spans.json new file mode 100644 index 00000000..efd4181f --- /dev/null +++ b/fluent-syntax/tests/fixtures/member_expressions.spans.json @@ -0,0 +1,231 @@ +{ + "body": [ + { + "type": "GroupComment", + "content": [ + "Member expressions in placeables." + ], + "span": { + "start": 0, + "end": 36 + } + }, + { + "type": "Message", + "id": { + "name": "message-attribute-expression-placeable", + "span": { + "start": 93, + "end": 131 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "msg", + "span": { + "start": 135, + "end": 138 + } + }, + "attribute": { + "name": "attr", + "span": { + "start": 139, + "end": 143 + } + }, + "span": { + "start": 135, + "end": 143 + } + }, + { + "start": 135, + "end": 143 + } + ], + "span": { + "start": 134, + "end": 143 + } + } + ], + "span": { + "start": 134, + "end": 146 + } + }, + "attributes": [], + "comment": { + "content": [ + "OK Message attributes may be interpolated in values." + ], + "span": { + "start": 38, + "end": 92 + } + }, + "span": { + "start": 93, + "end": 146 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Term attributes may not be used for interpolation." + ], + "span": { + "start": 146, + "end": 204 + } + }, + { + "type": "Junk", + "content": "term-attribute-expression-placeable = {-term.attr}\n\n\n", + "span": { + "start": 205, + "end": 258 + } + }, + { + "type": "GroupComment", + "content": [ + "Member expressions in selectors." + ], + "span": { + "start": 258, + "end": 293 + } + }, + { + "type": "Message", + "id": { + "name": "term-attribute-expression-selector", + "span": { + "start": 342, + "end": 376 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "TermReference", + "id": { + "name": "term", + "span": { + "start": 381, + "end": 385 + } + }, + "attribute": { + "name": "attr", + "span": { + "start": 386, + "end": 390 + } + }, + "arguments": null, + "span": { + "start": 380, + "end": 391 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 399, + "end": 402 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 404, + "end": 410 + } + } + ], + "span": { + "start": 404, + "end": 410 + } + }, + "default": true, + "span": { + "start": 397, + "end": 410 + } + } + ], + "span": { + "start": 380, + "end": 410 + } + }, + "span": { + "start": 379, + "end": 410 + } + } + ], + "span": { + "start": 379, + "end": 412 + } + }, + "attributes": [], + "comment": { + "content": [ + "OK Term attributes may be used as selectors." + ], + "span": { + "start": 295, + "end": 341 + } + }, + "span": { + "start": 342, + "end": 412 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Message attributes may not be used as selectors." + ], + "span": { + "start": 412, + "end": 468 + } + }, + { + "type": "Junk", + "content": "message-attribute-expression-selector = {msg.attr ->\n *[key] Value\n}\n", + "span": { + "start": 469, + "end": 540 + } + } + ], + "span": { + "start": 0, + "end": 540 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/messages.spans.json b/fluent-syntax/tests/fixtures/messages.spans.json new file mode 100644 index 00000000..03fbf80e --- /dev/null +++ b/fluent-syntax/tests/fixtures/messages.spans.json @@ -0,0 +1,790 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "key01", + "span": { + "start": 0, + "end": 5 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 8, + "end": 14 + } + } + ], + "span": { + "start": 8, + "end": 15 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 15 + } + }, + { + "type": "Message", + "id": { + "name": "key02", + "span": { + "start": 15, + "end": 20 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 23, + "end": 29 + } + } + ], + "span": { + "start": 23, + "end": 29 + } + }, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 34, + "end": 38 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute", + "span": { + "start": 41, + "end": 51 + } + } + ], + "span": { + "start": 41, + "end": 52 + } + }, + "span": { + "start": 51, + "end": 52 + } + } + ], + "comment": null, + "span": { + "start": 15, + "end": 52 + } + }, + { + "type": "Message", + "id": { + "name": "key02", + "span": { + "start": 52, + "end": 57 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 60, + "end": 66 + } + } + ], + "span": { + "start": 60, + "end": 66 + } + }, + "attributes": [ + { + "id": { + "name": "attr1", + "span": { + "start": 71, + "end": 76 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute 1", + "span": { + "start": 79, + "end": 91 + } + } + ], + "span": { + "start": 79, + "end": 91 + } + }, + "span": { + "start": 90, + "end": 91 + } + }, + { + "id": { + "name": "attr2", + "span": { + "start": 96, + "end": 101 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute 2", + "span": { + "start": 104, + "end": 116 + } + } + ], + "span": { + "start": 104, + "end": 117 + } + }, + "span": { + "start": 116, + "end": 117 + } + } + ], + "comment": null, + "span": { + "start": 52, + "end": 117 + } + }, + { + "type": "Message", + "id": { + "name": "key03", + "span": { + "start": 117, + "end": 122 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 130, + "end": 134 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute", + "span": { + "start": 137, + "end": 147 + } + } + ], + "span": { + "start": 137, + "end": 148 + } + }, + "span": { + "start": 147, + "end": 148 + } + } + ], + "comment": null, + "span": { + "start": 117, + "end": 148 + } + }, + { + "type": "Message", + "id": { + "name": "key04", + "span": { + "start": 148, + "end": 153 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attr1", + "span": { + "start": 161, + "end": 166 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute 1", + "span": { + "start": 169, + "end": 181 + } + } + ], + "span": { + "start": 169, + "end": 181 + } + }, + "span": { + "start": 180, + "end": 181 + } + }, + { + "id": { + "name": "attr2", + "span": { + "start": 186, + "end": 191 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute 2", + "span": { + "start": 194, + "end": 206 + } + } + ], + "span": { + "start": 194, + "end": 207 + } + }, + "span": { + "start": 206, + "end": 207 + } + } + ], + "comment": null, + "span": { + "start": 148, + "end": 207 + } + }, + { + "type": "Message", + "id": { + "name": "key05", + "span": { + "start": 231, + "end": 236 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attr1", + "span": { + "start": 260, + "end": 265 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute 1", + "span": { + "start": 268, + "end": 280 + } + } + ], + "span": { + "start": 268, + "end": 281 + } + }, + "span": { + "start": 280, + "end": 281 + } + } + ], + "comment": { + "content": [ + " < whitespace >" + ], + "span": { + "start": 207, + "end": 230 + } + }, + "span": { + "start": 231, + "end": 281 + } + }, + { + "type": "Message", + "id": { + "name": "no-whitespace", + "span": { + "start": 281, + "end": 294 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 295, + "end": 301 + } + } + ], + "span": { + "start": 295, + "end": 301 + } + }, + "attributes": [ + { + "id": { + "name": "attr1", + "span": { + "start": 306, + "end": 311 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute 1", + "span": { + "start": 312, + "end": 324 + } + } + ], + "span": { + "start": 312, + "end": 325 + } + }, + "span": { + "start": 324, + "end": 325 + } + } + ], + "comment": null, + "span": { + "start": 281, + "end": 325 + } + }, + { + "type": "Message", + "id": { + "name": "extra-whitespace", + "span": { + "start": 325, + "end": 341 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 348, + "end": 354 + } + } + ], + "span": { + "start": 348, + "end": 354 + } + }, + "attributes": [ + { + "id": { + "name": "attr1", + "span": { + "start": 359, + "end": 364 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute 1", + "span": { + "start": 374, + "end": 386 + } + } + ], + "span": { + "start": 374, + "end": 387 + } + }, + "span": { + "start": 386, + "end": 387 + } + } + ], + "comment": null, + "span": { + "start": 325, + "end": 387 + } + }, + { + "type": "Message", + "id": { + "name": "key06", + "span": { + "start": 387, + "end": 392 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "", + "span": { + "start": 396, + "end": 398 + } + }, + { + "start": 396, + "end": 398 + } + ], + "span": { + "start": 395, + "end": 398 + } + } + ], + "span": { + "start": 395, + "end": 401 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 387, + "end": 401 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Missing value" + ], + "span": { + "start": 401, + "end": 421 + } + }, + { + "type": "Junk", + "content": "key07 =\n\n", + "span": { + "start": 422, + "end": 431 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Missing =" + ], + "span": { + "start": 431, + "end": 447 + } + }, + { + "type": "Junk", + "content": "key08\n\n", + "span": { + "start": 448, + "end": 455 + } + }, + { + "type": "Message", + "id": { + "name": "KEY09", + "span": { + "start": 455, + "end": 460 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value 09", + "span": { + "start": 463, + "end": 472 + } + } + ], + "span": { + "start": 463, + "end": 473 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 455, + "end": 473 + } + }, + { + "type": "Message", + "id": { + "name": "key-10", + "span": { + "start": 473, + "end": 479 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value 10", + "span": { + "start": 482, + "end": 491 + } + } + ], + "span": { + "start": 482, + "end": 491 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 473, + "end": 491 + } + }, + { + "type": "Message", + "id": { + "name": "key_11", + "span": { + "start": 491, + "end": 497 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value 11", + "span": { + "start": 500, + "end": 509 + } + } + ], + "span": { + "start": 500, + "end": 509 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 491, + "end": 509 + } + }, + { + "type": "Message", + "id": { + "name": "key-12-", + "span": { + "start": 509, + "end": 516 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value 12", + "span": { + "start": 519, + "end": 528 + } + } + ], + "span": { + "start": 519, + "end": 528 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 509, + "end": 528 + } + }, + { + "type": "Message", + "id": { + "name": "key_13_", + "span": { + "start": 528, + "end": 535 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value 13", + "span": { + "start": 538, + "end": 547 + } + } + ], + "span": { + "start": 538, + "end": 548 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 528, + "end": 548 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Invalid id" + ], + "span": { + "start": 548, + "end": 565 + } + }, + { + "type": "Junk", + "content": "0err-14 = Value 14\n\n", + "span": { + "start": 566, + "end": 586 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Invalid id" + ], + "span": { + "start": 586, + "end": 603 + } + }, + { + "type": "Junk", + "content": "err-15? = Value 15\n\n", + "span": { + "start": 604, + "end": 624 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Invalid id" + ], + "span": { + "start": 624, + "end": 641 + } + }, + { + "type": "Junk", + "content": "err-ąę-16 = Value 16\n", + "span": { + "start": 642, + "end": 665 + } + } + ], + "span": { + "start": 0, + "end": 665 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/mixed_entries.spans.json b/fluent-syntax/tests/fixtures/mixed_entries.spans.json new file mode 100644 index 00000000..dd4d3852 --- /dev/null +++ b/fluent-syntax/tests/fixtures/mixed_entries.spans.json @@ -0,0 +1,255 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "License Comment" + ], + "span": { + "start": 0, + "end": 17 + } + }, + { + "type": "ResourceComment", + "content": [ + "Resource Comment" + ], + "span": { + "start": 19, + "end": 39 + } + }, + { + "type": "Term", + "id": { + "name": "brand-name", + "span": { + "start": 42, + "end": 52 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Aurora", + "span": { + "start": 55, + "end": 62 + } + } + ], + "span": { + "start": 55, + "end": 63 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 41, + "end": 63 + } + }, + { + "type": "GroupComment", + "content": [ + "Group Comment" + ], + "span": { + "start": 63, + "end": 79 + } + }, + { + "type": "Message", + "id": { + "name": "key01", + "span": { + "start": 81, + "end": 86 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 94, + "end": 98 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute", + "span": { + "start": 101, + "end": 111 + } + } + ], + "span": { + "start": 101, + "end": 112 + } + }, + "span": { + "start": 111, + "end": 112 + } + } + ], + "comment": null, + "span": { + "start": 81, + "end": 112 + } + }, + { + "type": "Junk", + "content": "ą=Invalid identifier\nć=Another one\n\n", + "span": { + "start": 112, + "end": 150 + } + }, + { + "type": "Message", + "id": { + "name": "key02", + "span": { + "start": 168, + "end": 173 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 176, + "end": 182 + } + } + ], + "span": { + "start": 176, + "end": 183 + } + }, + "attributes": [], + "comment": { + "content": [ + "Message Comment" + ], + "span": { + "start": 150, + "end": 167 + } + }, + "span": { + "start": 168, + "end": 183 + } + }, + { + "type": "Comment", + "content": [ + "Standalone Comment" + ], + "span": { + "start": 183, + "end": 203 + } + }, + { + "type": "Junk", + "content": " .attr = Dangling attribute\n\n", + "span": { + "start": 204, + "end": 236 + } + }, + { + "type": "Message", + "id": { + "name": "key03", + "span": { + "start": 294, + "end": 299 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value 03", + "span": { + "start": 302, + "end": 311 + } + } + ], + "span": { + "start": 302, + "end": 317 + } + }, + "attributes": [], + "comment": { + "content": [ + "There are 5 spaces on the line between key03 and key04." + ], + "span": { + "start": 236, + "end": 293 + } + }, + "span": { + "start": 294, + "end": 317 + } + }, + { + "type": "Message", + "id": { + "name": "key04", + "span": { + "start": 317, + "end": 322 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value 04", + "span": { + "start": 325, + "end": 334 + } + } + ], + "span": { + "start": 325, + "end": 334 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 317, + "end": 334 + } + } + ], + "span": { + "start": 0, + "end": 334 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/multiline_values.spans.json b/fluent-syntax/tests/fixtures/multiline_values.spans.json new file mode 100644 index 00000000..fdd2307a --- /dev/null +++ b/fluent-syntax/tests/fixtures/multiline_values.spans.json @@ -0,0 +1,782 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "key01", + "span": { + "start": 0, + "end": 5 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A multiline value\n", + "span": { + "start": 8, + "end": 26 + } + }, + { + "type": "TextElement", + "value": "continued on the next line\n", + "span": { + "start": 30, + "end": 57 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 57, + "end": 58 + } + }, + { + "type": "TextElement", + "value": "and also down here.", + "span": { + "start": 62, + "end": 82 + } + } + ], + "span": { + "start": 8, + "end": 83 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 83 + } + }, + { + "type": "Message", + "id": { + "name": "key02", + "span": { + "start": 83, + "end": 88 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A multiline value starting\n", + "span": { + "start": 95, + "end": 122 + } + }, + { + "type": "TextElement", + "value": "on a new line.", + "span": { + "start": 126, + "end": 141 + } + } + ], + "span": { + "start": 90, + "end": 142 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 83, + "end": 142 + } + }, + { + "type": "Message", + "id": { + "name": "key03", + "span": { + "start": 142, + "end": 147 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 155, + "end": 159 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A multiline attribute value\n", + "span": { + "start": 162, + "end": 190 + } + }, + { + "type": "TextElement", + "value": "continued on the next line\n", + "span": { + "start": 198, + "end": 225 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 225, + "end": 226 + } + }, + { + "type": "TextElement", + "value": "and also down here.", + "span": { + "start": 234, + "end": 254 + } + } + ], + "span": { + "start": 162, + "end": 255 + } + }, + "span": { + "start": 254, + "end": 255 + } + } + ], + "comment": null, + "span": { + "start": 142, + "end": 255 + } + }, + { + "type": "Message", + "id": { + "name": "key04", + "span": { + "start": 255, + "end": 260 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 268, + "end": 272 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A multiline attribute value\n", + "span": { + "start": 283, + "end": 311 + } + }, + { + "type": "TextElement", + "value": "staring on a new line", + "span": { + "start": 319, + "end": 341 + } + } + ], + "span": { + "start": 274, + "end": 342 + } + }, + "span": { + "start": 341, + "end": 342 + } + } + ], + "comment": null, + "span": { + "start": 255, + "end": 342 + } + }, + { + "type": "Message", + "id": { + "name": "key05", + "span": { + "start": 342, + "end": 347 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A multiline value with non-standard\n", + "span": { + "start": 352, + "end": 388 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 388, + "end": 389 + } + }, + { + "type": "TextElement", + "value": " indentation.", + "span": { + "start": 390, + "end": 407 + } + } + ], + "span": { + "start": 349, + "end": 408 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 342, + "end": 408 + } + }, + { + "type": "Message", + "id": { + "name": "key06", + "span": { + "start": 408, + "end": 413 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A multiline value with ", + "span": { + "start": 420, + "end": 443 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "placeables", + "span": { + "start": 444, + "end": 456 + } + }, + { + "start": 444, + "end": 456 + } + ], + "span": { + "start": 443, + "end": 456 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 457, + "end": 458 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "at", + "span": { + "start": 463, + "end": 467 + } + }, + { + "start": 463, + "end": 467 + } + ], + "span": { + "start": 462, + "end": 467 + } + }, + { + "type": "TextElement", + "value": " the beginning and the end\n", + "span": { + "start": 468, + "end": 495 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "of lines", + "span": { + "start": 500, + "end": 510 + } + }, + { + "start": 500, + "end": 510 + } + ], + "span": { + "start": 499, + "end": 510 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 512, + "end": 515 + } + }, + { + "start": 512, + "end": 515 + } + ], + "span": { + "start": 511, + "end": 515 + } + } + ], + "span": { + "start": 415, + "end": 518 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 408, + "end": 518 + } + }, + { + "type": "Message", + "id": { + "name": "key07", + "span": { + "start": 518, + "end": 523 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "A multiline value", + "span": { + "start": 531, + "end": 550 + } + }, + { + "start": 531, + "end": 550 + } + ], + "span": { + "start": 530, + "end": 550 + } + }, + { + "type": "TextElement", + "value": " starting and ending ", + "span": { + "start": 551, + "end": 572 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "with a placeable", + "span": { + "start": 573, + "end": 591 + } + }, + { + "start": 573, + "end": 591 + } + ], + "span": { + "start": 572, + "end": 591 + } + } + ], + "span": { + "start": 525, + "end": 594 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 518, + "end": 594 + } + }, + { + "type": "Message", + "id": { + "name": "key08", + "span": { + "start": 594, + "end": 599 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Leading and trailing whitespace.", + "span": { + "start": 606, + "end": 644 + } + } + ], + "span": { + "start": 606, + "end": 645 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 594, + "end": 645 + } + }, + { + "type": "Message", + "id": { + "name": "key09", + "span": { + "start": 645, + "end": 650 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "zero\n", + "span": { + "start": 653, + "end": 658 + } + }, + { + "type": "TextElement", + "value": " three\n", + "span": { + "start": 660, + "end": 669 + } + }, + { + "type": "TextElement", + "value": " two\n", + "span": { + "start": 671, + "end": 677 + } + }, + { + "type": "TextElement", + "value": " one\n", + "span": { + "start": 679, + "end": 684 + } + }, + { + "type": "TextElement", + "value": "zero", + "span": { + "start": 686, + "end": 691 + } + } + ], + "span": { + "start": 653, + "end": 692 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 645, + "end": 692 + } + }, + { + "type": "Message", + "id": { + "name": "key10", + "span": { + "start": 692, + "end": 697 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": " two\n", + "span": { + "start": 704, + "end": 710 + } + }, + { + "type": "TextElement", + "value": "zero\n", + "span": { + "start": 714, + "end": 719 + } + }, + { + "type": "TextElement", + "value": " four", + "span": { + "start": 723, + "end": 732 + } + } + ], + "span": { + "start": 699, + "end": 733 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 692, + "end": 733 + } + }, + { + "type": "Message", + "id": { + "name": "key11", + "span": { + "start": 733, + "end": 738 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": " two\n", + "span": { + "start": 747, + "end": 753 + } + }, + { + "type": "TextElement", + "value": "zero", + "span": { + "start": 757, + "end": 762 + } + } + ], + "span": { + "start": 740, + "end": 763 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 733, + "end": 763 + } + }, + { + "type": "Message", + "id": { + "name": "key12", + "span": { + "start": 763, + "end": 768 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 772, + "end": 775 + } + }, + { + "start": 772, + "end": 775 + } + ], + "span": { + "start": 771, + "end": 775 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 776, + "end": 777 + } + }, + { + "type": "TextElement", + "value": " four", + "span": { + "start": 777, + "end": 786 + } + } + ], + "span": { + "start": 770, + "end": 787 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 763, + "end": 787 + } + }, + { + "type": "Message", + "id": { + "name": "key13", + "span": { + "start": 787, + "end": 792 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": " four\n", + "span": { + "start": 795, + "end": 804 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": ".", + "span": { + "start": 805, + "end": 808 + } + }, + { + "start": 805, + "end": 808 + } + ], + "span": { + "start": 804, + "end": 808 + } + } + ], + "span": { + "start": 794, + "end": 810 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 787, + "end": 810 + } + } + ], + "span": { + "start": 0, + "end": 810 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/numbers.spans.json b/fluent-syntax/tests/fixtures/numbers.spans.json new file mode 100644 index 00000000..1a84236f --- /dev/null +++ b/fluent-syntax/tests/fixtures/numbers.spans.json @@ -0,0 +1,1064 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "int-zero", + "span": { + "start": 0, + "end": 8 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "0", + "span": { + "start": 12, + "end": 13 + } + }, + { + "start": 12, + "end": 13 + } + ], + "span": { + "start": 11, + "end": 13 + } + } + ], + "span": { + "start": 11, + "end": 15 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 15 + } + }, + { + "type": "Message", + "id": { + "name": "int-positive", + "span": { + "start": 15, + "end": 27 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 31, + "end": 32 + } + }, + { + "start": 31, + "end": 32 + } + ], + "span": { + "start": 30, + "end": 32 + } + } + ], + "span": { + "start": 30, + "end": 34 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 15, + "end": 34 + } + }, + { + "type": "Message", + "id": { + "name": "int-negative", + "span": { + "start": 34, + "end": 46 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-1", + "span": { + "start": 50, + "end": 52 + } + }, + { + "start": 50, + "end": 52 + } + ], + "span": { + "start": 49, + "end": 52 + } + } + ], + "span": { + "start": 49, + "end": 54 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 34, + "end": 54 + } + }, + { + "type": "Message", + "id": { + "name": "int-negative-zero", + "span": { + "start": 54, + "end": 71 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-0", + "span": { + "start": 75, + "end": 77 + } + }, + { + "start": 75, + "end": 77 + } + ], + "span": { + "start": 74, + "end": 77 + } + } + ], + "span": { + "start": 74, + "end": 80 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 54, + "end": 80 + } + }, + { + "type": "Message", + "id": { + "name": "int-positive-padded", + "span": { + "start": 80, + "end": 99 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "01", + "span": { + "start": 103, + "end": 105 + } + }, + { + "start": 103, + "end": 105 + } + ], + "span": { + "start": 102, + "end": 105 + } + } + ], + "span": { + "start": 102, + "end": 107 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 80, + "end": 107 + } + }, + { + "type": "Message", + "id": { + "name": "int-negative-padded", + "span": { + "start": 107, + "end": 126 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-01", + "span": { + "start": 130, + "end": 133 + } + }, + { + "start": 130, + "end": 133 + } + ], + "span": { + "start": 129, + "end": 133 + } + } + ], + "span": { + "start": 129, + "end": 135 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 107, + "end": 135 + } + }, + { + "type": "Message", + "id": { + "name": "int-zero-padded", + "span": { + "start": 135, + "end": 150 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "00", + "span": { + "start": 154, + "end": 156 + } + }, + { + "start": 154, + "end": 156 + } + ], + "span": { + "start": 153, + "end": 156 + } + } + ], + "span": { + "start": 153, + "end": 158 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 135, + "end": 158 + } + }, + { + "type": "Message", + "id": { + "name": "int-negative-zero-padded", + "span": { + "start": 158, + "end": 182 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-00", + "span": { + "start": 186, + "end": 189 + } + }, + { + "start": 186, + "end": 189 + } + ], + "span": { + "start": 185, + "end": 189 + } + } + ], + "span": { + "start": 185, + "end": 192 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 158, + "end": 192 + } + }, + { + "type": "Message", + "id": { + "name": "float-zero", + "span": { + "start": 192, + "end": 202 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "0.0", + "span": { + "start": 206, + "end": 209 + } + }, + { + "start": 206, + "end": 209 + } + ], + "span": { + "start": 205, + "end": 209 + } + } + ], + "span": { + "start": 205, + "end": 211 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 192, + "end": 211 + } + }, + { + "type": "Message", + "id": { + "name": "float-positive", + "span": { + "start": 211, + "end": 225 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "0.01", + "span": { + "start": 229, + "end": 233 + } + }, + { + "start": 229, + "end": 233 + } + ], + "span": { + "start": 228, + "end": 233 + } + } + ], + "span": { + "start": 228, + "end": 235 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 211, + "end": 235 + } + }, + { + "type": "Message", + "id": { + "name": "float-positive-one", + "span": { + "start": 235, + "end": 253 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "1.03", + "span": { + "start": 257, + "end": 261 + } + }, + { + "start": 257, + "end": 261 + } + ], + "span": { + "start": 256, + "end": 261 + } + } + ], + "span": { + "start": 256, + "end": 263 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 235, + "end": 263 + } + }, + { + "type": "Message", + "id": { + "name": "float-positive-without-fraction", + "span": { + "start": 263, + "end": 294 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "1.000", + "span": { + "start": 298, + "end": 303 + } + }, + { + "start": 298, + "end": 303 + } + ], + "span": { + "start": 297, + "end": 303 + } + } + ], + "span": { + "start": 297, + "end": 306 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 263, + "end": 306 + } + }, + { + "type": "Message", + "id": { + "name": "float-negative", + "span": { + "start": 306, + "end": 320 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-0.01", + "span": { + "start": 324, + "end": 329 + } + }, + { + "start": 324, + "end": 329 + } + ], + "span": { + "start": 323, + "end": 329 + } + } + ], + "span": { + "start": 323, + "end": 331 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 306, + "end": 331 + } + }, + { + "type": "Message", + "id": { + "name": "float-negative-one", + "span": { + "start": 331, + "end": 349 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-1.03", + "span": { + "start": 353, + "end": 358 + } + }, + { + "start": 353, + "end": 358 + } + ], + "span": { + "start": 352, + "end": 358 + } + } + ], + "span": { + "start": 352, + "end": 360 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 331, + "end": 360 + } + }, + { + "type": "Message", + "id": { + "name": "float-negative-zero", + "span": { + "start": 360, + "end": 379 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-0.0", + "span": { + "start": 383, + "end": 387 + } + }, + { + "start": 383, + "end": 387 + } + ], + "span": { + "start": 382, + "end": 387 + } + } + ], + "span": { + "start": 382, + "end": 389 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 360, + "end": 389 + } + }, + { + "type": "Message", + "id": { + "name": "float-negative-without-fraction", + "span": { + "start": 389, + "end": 420 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-1.000", + "span": { + "start": 424, + "end": 430 + } + }, + { + "start": 424, + "end": 430 + } + ], + "span": { + "start": 423, + "end": 430 + } + } + ], + "span": { + "start": 423, + "end": 433 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 389, + "end": 433 + } + }, + { + "type": "Message", + "id": { + "name": "float-positive-padded-left", + "span": { + "start": 433, + "end": 459 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "01.03", + "span": { + "start": 463, + "end": 468 + } + }, + { + "start": 463, + "end": 468 + } + ], + "span": { + "start": 462, + "end": 468 + } + } + ], + "span": { + "start": 462, + "end": 470 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 433, + "end": 470 + } + }, + { + "type": "Message", + "id": { + "name": "float-positive-padded-right", + "span": { + "start": 470, + "end": 497 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "1.0300", + "span": { + "start": 501, + "end": 507 + } + }, + { + "start": 501, + "end": 507 + } + ], + "span": { + "start": 500, + "end": 507 + } + } + ], + "span": { + "start": 500, + "end": 509 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 470, + "end": 509 + } + }, + { + "type": "Message", + "id": { + "name": "float-positive-padded-both", + "span": { + "start": 509, + "end": 535 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "01.0300", + "span": { + "start": 539, + "end": 546 + } + }, + { + "start": 539, + "end": 546 + } + ], + "span": { + "start": 538, + "end": 546 + } + } + ], + "span": { + "start": 538, + "end": 549 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 509, + "end": 549 + } + }, + { + "type": "Message", + "id": { + "name": "float-negative-padded-left", + "span": { + "start": 549, + "end": 575 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-01.03", + "span": { + "start": 579, + "end": 585 + } + }, + { + "start": 579, + "end": 585 + } + ], + "span": { + "start": 578, + "end": 585 + } + } + ], + "span": { + "start": 578, + "end": 587 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 549, + "end": 587 + } + }, + { + "type": "Message", + "id": { + "name": "float-negative-padded-right", + "span": { + "start": 587, + "end": 614 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-1.0300", + "span": { + "start": 618, + "end": 625 + } + }, + { + "start": 618, + "end": 625 + } + ], + "span": { + "start": 617, + "end": 625 + } + } + ], + "span": { + "start": 617, + "end": 627 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 587, + "end": 627 + } + }, + { + "type": "Message", + "id": { + "name": "float-negative-padded-both", + "span": { + "start": 627, + "end": 653 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "-01.0300", + "span": { + "start": 657, + "end": 665 + } + }, + { + "start": 657, + "end": 665 + } + ], + "span": { + "start": 656, + "end": 665 + } + } + ], + "span": { + "start": 656, + "end": 669 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 627, + "end": 669 + } + }, + { + "type": "GroupComment", + "content": [ + "ERRORS" + ], + "span": { + "start": 669, + "end": 678 + } + }, + { + "type": "Junk", + "content": "err01 = {1.}\n", + "span": { + "start": 680, + "end": 693 + } + }, + { + "type": "Junk", + "content": "err02 = {.02}\n", + "span": { + "start": 693, + "end": 707 + } + }, + { + "type": "Junk", + "content": "err03 = {1.02.03}\n", + "span": { + "start": 707, + "end": 725 + } + }, + { + "type": "Junk", + "content": "err04 = {1. 02}\n", + "span": { + "start": 725, + "end": 741 + } + }, + { + "type": "Junk", + "content": "err05 = {1 .02}\n", + "span": { + "start": 741, + "end": 757 + } + }, + { + "type": "Junk", + "content": "err06 = {- 1}\n", + "span": { + "start": 757, + "end": 771 + } + }, + { + "type": "Junk", + "content": "err07 = {1,02}\n", + "span": { + "start": 771, + "end": 786 + } + } + ], + "span": { + "start": 0, + "end": 786 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/obsolete.spans.json b/fluent-syntax/tests/fixtures/obsolete.spans.json new file mode 100644 index 00000000..b1416217 --- /dev/null +++ b/fluent-syntax/tests/fixtures/obsolete.spans.json @@ -0,0 +1,88 @@ +{ + "body": [ + { + "type": "ResourceComment", + "content": [ + "The syntax in this file has been discontinued. It is no longer part of the", + "Fluent specification and should not be implemented nor used. We're keeping", + "these fixtures around to protect against accidental syntax reuse." + ], + "span": { + "start": 0, + "end": 227 + } + }, + { + "type": "GroupComment", + "content": [ + "Variant lists." + ], + "span": { + "start": 230, + "end": 247 + } + }, + { + "type": "Junk", + "content": "message-variant-list =\n {\n *[key] Value\n }\n\n", + "span": { + "start": 249, + "end": 305 + } + }, + { + "type": "Junk", + "content": "-term-variant-list =\n {\n *[key] Value\n }\n\n\n", + "span": { + "start": 305, + "end": 360 + } + }, + { + "type": "GroupComment", + "content": [ + "Variant expressions." + ], + "span": { + "start": 360, + "end": 383 + } + }, + { + "type": "Junk", + "content": "message-variant-expression-placeable = {msg[case]}\n", + "span": { + "start": 385, + "end": 436 + } + }, + { + "type": "Junk", + "content": "message-variant-expression-selector = {msg[case] ->\n *[key] Value\n}\n\n", + "span": { + "start": 436, + "end": 507 + } + }, + { + "type": "Junk", + "content": "term-variant-expression-placeable = {-term[case]}\n", + "span": { + "start": 507, + "end": 557 + } + }, + { + "type": "Junk", + "content": "term-variant-expression-selector = {-term[case] ->\n *[key] Value\n}\n", + "span": { + "start": 557, + "end": 626 + } + } + ], + "span": { + "start": 0, + "end": 626 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/placeables.spans.json b/fluent-syntax/tests/fixtures/placeables.spans.json new file mode 100644 index 00000000..0e4cb290 --- /dev/null +++ b/fluent-syntax/tests/fixtures/placeables.spans.json @@ -0,0 +1,254 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "nested-placeable", + "span": { + "start": 0, + "end": 16 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "Placeable", + "expression": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 22, + "end": 23 + } + }, + { + "start": 22, + "end": 23 + } + ], + "span": { + "start": 21, + "end": 24 + } + }, + { + "start": 21, + "end": 24 + } + ], + "span": { + "start": 20, + "end": 25 + } + }, + { + "start": 20, + "end": 25 + } + ], + "span": { + "start": 19, + "end": 25 + } + } + ], + "span": { + "start": 19, + "end": 27 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 27 + } + }, + { + "type": "Message", + "id": { + "name": "padded-placeable", + "span": { + "start": 27, + "end": 43 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 49, + "end": 50 + } + }, + { + "start": 49, + "end": 52 + } + ], + "span": { + "start": 46, + "end": 52 + } + } + ], + "span": { + "start": 46, + "end": 54 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 27, + "end": 54 + } + }, + { + "type": "Message", + "id": { + "name": "sparse-placeable", + "span": { + "start": 54, + "end": 70 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "Placeable", + "expression": [ + { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 77, + "end": 78 + } + }, + { + "start": 77, + "end": 79 + } + ], + "span": { + "start": 75, + "end": 80 + } + }, + { + "start": 75, + "end": 81 + } + ], + "span": { + "start": 73, + "end": 81 + } + } + ], + "span": { + "start": 73, + "end": 84 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 54, + "end": 84 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Unmatched opening brace" + ], + "span": { + "start": 84, + "end": 115 + } + }, + { + "type": "Junk", + "content": "unmatched-open1 = { 1\n\n", + "span": { + "start": 116, + "end": 139 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Unmatched opening brace" + ], + "span": { + "start": 139, + "end": 170 + } + }, + { + "type": "Junk", + "content": "unmatched-open2 = {{ 1 }\n\n", + "span": { + "start": 171, + "end": 197 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Unmatched closing brace" + ], + "span": { + "start": 197, + "end": 228 + } + }, + { + "type": "Junk", + "content": "unmatched-close1 = 1 }\n\n", + "span": { + "start": 229, + "end": 253 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Unmatched closing brace" + ], + "span": { + "start": 253, + "end": 284 + } + }, + { + "type": "Junk", + "content": "unmatched-close2 = { 1 }}\n", + "span": { + "start": 285, + "end": 311 + } + } + ], + "span": { + "start": 0, + "end": 311 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/reference_expressions.spans.json b/fluent-syntax/tests/fixtures/reference_expressions.spans.json new file mode 100644 index 00000000..8218e968 --- /dev/null +++ b/fluent-syntax/tests/fixtures/reference_expressions.spans.json @@ -0,0 +1,385 @@ +{ + "body": [ + { + "type": "GroupComment", + "content": [ + "Reference expressions in placeables." + ], + "span": { + "start": 0, + "end": 39 + } + }, + { + "type": "Message", + "id": { + "name": "message-reference-placeable", + "span": { + "start": 41, + "end": 68 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "msg", + "span": { + "start": 72, + "end": 75 + } + }, + "attribute": null, + "span": { + "start": 72, + "end": 75 + } + }, + { + "start": 72, + "end": 75 + } + ], + "span": { + "start": 71, + "end": 75 + } + } + ], + "span": { + "start": 71, + "end": 77 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 41, + "end": 77 + } + }, + { + "type": "Message", + "id": { + "name": "term-reference-placeable", + "span": { + "start": 77, + "end": 101 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "term", + "span": { + "start": 106, + "end": 110 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 105, + "end": 110 + } + }, + { + "start": 105, + "end": 110 + } + ], + "span": { + "start": 104, + "end": 110 + } + } + ], + "span": { + "start": 104, + "end": 112 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 77, + "end": 112 + } + }, + { + "type": "Message", + "id": { + "name": "variable-reference-placeable", + "span": { + "start": 112, + "end": 140 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "var", + "span": { + "start": 145, + "end": 148 + } + }, + "span": { + "start": 144, + "end": 148 + } + }, + { + "start": 144, + "end": 148 + } + ], + "span": { + "start": 143, + "end": 148 + } + } + ], + "span": { + "start": 143, + "end": 151 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 112, + "end": 151 + } + }, + { + "type": "Message", + "id": { + "name": "function-reference-placeable", + "span": { + "start": 257, + "end": 285 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "FUN", + "span": { + "start": 289, + "end": 292 + } + }, + "attribute": null, + "span": { + "start": 289, + "end": 292 + } + }, + { + "start": 289, + "end": 292 + } + ], + "span": { + "start": 288, + "end": 292 + } + } + ], + "span": { + "start": 288, + "end": 296 + } + }, + "attributes": [], + "comment": { + "content": [ + "Function references are invalid outside of call expressions.", + "This parses as a valid MessageReference." + ], + "span": { + "start": 151, + "end": 256 + } + }, + "span": { + "start": 257, + "end": 296 + } + }, + { + "type": "GroupComment", + "content": [ + "Reference expressions in selectors." + ], + "span": { + "start": 296, + "end": 334 + } + }, + { + "type": "Message", + "id": { + "name": "variable-reference-selector", + "span": { + "start": 336, + "end": 363 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "var", + "span": { + "start": 368, + "end": 371 + } + }, + "span": { + "start": 367, + "end": 371 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 380, + "end": 383 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 385, + "end": 391 + } + } + ], + "span": { + "start": 385, + "end": 391 + } + }, + "default": true, + "span": { + "start": 378, + "end": 391 + } + } + ], + "span": { + "start": 367, + "end": 391 + } + }, + "span": { + "start": 366, + "end": 391 + } + } + ], + "span": { + "start": 366, + "end": 394 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 336, + "end": 394 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Message values may not be used as selectors." + ], + "span": { + "start": 394, + "end": 446 + } + }, + { + "type": "Junk", + "content": "message-reference-selector = {msg ->\n *[key] Value\n}\n", + "span": { + "start": 447, + "end": 502 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Term values may not be used as selectors." + ], + "span": { + "start": 502, + "end": 551 + } + }, + { + "type": "Junk", + "content": "term-reference-selector = {-term ->\n *[key] Value\n}\n", + "span": { + "start": 552, + "end": 606 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Function references are invalid outside of call expressions, and this", + "parses as a MessageReference which isn't a valid selector." + ], + "span": { + "start": 606, + "end": 744 + } + }, + { + "type": "Junk", + "content": "function-expression-selector = {FUN ->\n *[key] Value\n}\n", + "span": { + "start": 745, + "end": 802 + } + } + ], + "span": { + "start": 0, + "end": 802 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/select_expressions.spans.json b/fluent-syntax/tests/fixtures/select_expressions.spans.json new file mode 100644 index 00000000..15c1cf58 --- /dev/null +++ b/fluent-syntax/tests/fixtures/select_expressions.spans.json @@ -0,0 +1,699 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "new-messages", + "span": { + "start": 0, + "end": 12 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "BUILTIN", + "span": { + "start": 21, + "end": 28 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 28, + "end": 30 + } + }, + "span": { + "start": 21, + "end": 30 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "NumberLiteral", + "value": "0", + "span": { + "start": 43, + "end": 44 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Zero", + "span": { + "start": 46, + "end": 51 + } + } + ], + "span": { + "start": 46, + "end": 51 + } + }, + "default": false, + "span": { + "start": 42, + "end": 51 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 60, + "end": 65 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "", + "span": { + "start": 68, + "end": 70 + } + }, + { + "start": 68, + "end": 70 + } + ], + "span": { + "start": 67, + "end": 70 + } + }, + { + "type": "TextElement", + "value": "Other", + "span": { + "start": 71, + "end": 77 + } + } + ], + "span": { + "start": 67, + "end": 77 + } + }, + "default": true, + "span": { + "start": 58, + "end": 77 + } + } + ], + "span": { + "start": 21, + "end": 81 + } + }, + "span": { + "start": 19, + "end": 81 + } + } + ], + "span": { + "start": 14, + "end": 84 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 84 + } + }, + { + "type": "Message", + "id": { + "name": "valid-selector-term-attribute", + "span": { + "start": 84, + "end": 113 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "TermReference", + "id": { + "name": "term", + "span": { + "start": 123, + "end": 127 + } + }, + "attribute": { + "name": "case", + "span": { + "start": 128, + "end": 132 + } + }, + "arguments": null, + "span": { + "start": 122, + "end": 133 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 145, + "end": 148 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "value", + "span": { + "start": 150, + "end": 156 + } + } + ], + "span": { + "start": 150, + "end": 156 + } + }, + "default": true, + "span": { + "start": 143, + "end": 156 + } + } + ], + "span": { + "start": 122, + "end": 160 + } + }, + "span": { + "start": 120, + "end": 160 + } + } + ], + "span": { + "start": 115, + "end": 163 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 84, + "end": 163 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Term values are not valid selectors" + ], + "span": { + "start": 163, + "end": 206 + } + }, + { + "type": "Junk", + "content": "invalid-selector-term-value =\n { -term ->\n *[key] value\n }\n\n", + "span": { + "start": 207, + "end": 279 + } + }, + { + "type": "Comment", + "content": [ + "ERROR CallExpressions on Terms are similar to TermReferences" + ], + "span": { + "start": 279, + "end": 341 + } + }, + { + "type": "Junk", + "content": "invalid-selector-term-variant =\n { -term(case: \"nominative\") ->\n *[key] value\n }\n\n", + "span": { + "start": 342, + "end": 436 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Nested expressions are not valid selectors" + ], + "span": { + "start": 436, + "end": 486 + } + }, + { + "type": "Junk", + "content": "invalid-selector-nested-expression =\n { { 3 } ->\n *[key] default\n }\n\n", + "span": { + "start": 487, + "end": 569 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Select expressions are not valid selectors" + ], + "span": { + "start": 569, + "end": 619 + } + }, + { + "type": "Junk", + "content": "invalid-selector-select-expression =\n { { $sel ->\n *[key] value\n } ->\n *[key] default\n }\n\n", + "span": { + "start": 620, + "end": 737 + } + }, + { + "type": "Message", + "id": { + "name": "empty-variant", + "span": { + "start": 737, + "end": 750 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "sel", + "span": { + "start": 760, + "end": 763 + } + }, + "span": { + "start": 759, + "end": 763 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 776, + "end": 779 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "", + "span": { + "start": 782, + "end": 784 + } + }, + { + "start": 782, + "end": 784 + } + ], + "span": { + "start": 781, + "end": 784 + } + } + ], + "span": { + "start": 781, + "end": 786 + } + }, + "default": true, + "span": { + "start": 774, + "end": 786 + } + } + ], + "span": { + "start": 759, + "end": 790 + } + }, + "span": { + "start": 757, + "end": 790 + } + } + ], + "span": { + "start": 752, + "end": 793 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 737, + "end": 793 + } + }, + { + "type": "Message", + "id": { + "name": "reduced-whitespace", + "span": { + "start": 793, + "end": 811 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "FOO", + "span": { + "start": 819, + "end": 822 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 822, + "end": 824 + } + }, + "span": { + "start": 819, + "end": 824 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 836, + "end": 839 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "", + "span": { + "start": 842, + "end": 844 + } + }, + { + "start": 842, + "end": 844 + } + ], + "span": { + "start": 841, + "end": 844 + } + } + ], + "span": { + "start": 841, + "end": 846 + } + }, + "default": true, + "span": { + "start": 834, + "end": 846 + } + } + ], + "span": { + "start": 819, + "end": 850 + } + }, + "span": { + "start": 818, + "end": 850 + } + } + ], + "span": { + "start": 813, + "end": 853 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 793, + "end": 853 + } + }, + { + "type": "Message", + "id": { + "name": "nested-select", + "span": { + "start": 853, + "end": 866 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "sel", + "span": { + "start": 876, + "end": 879 + } + }, + "span": { + "start": 875, + "end": 879 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "one", + "span": { + "start": 892, + "end": 895 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "sel", + "span": { + "start": 900, + "end": 903 + } + }, + "span": { + "start": 899, + "end": 903 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "two", + "span": { + "start": 919, + "end": 922 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 924, + "end": 930 + } + } + ], + "span": { + "start": 924, + "end": 930 + } + }, + "default": true, + "span": { + "start": 917, + "end": 930 + } + } + ], + "span": { + "start": 899, + "end": 937 + } + }, + "span": { + "start": 897, + "end": 937 + } + } + ], + "span": { + "start": 897, + "end": 939 + } + }, + "default": true, + "span": { + "start": 890, + "end": 939 + } + } + ], + "span": { + "start": 875, + "end": 943 + } + }, + "span": { + "start": 873, + "end": 943 + } + } + ], + "span": { + "start": 868, + "end": 946 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 853, + "end": 946 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Missing selector" + ], + "span": { + "start": 946, + "end": 970 + } + }, + { + "type": "Junk", + "content": "missing-selector =\n {\n *[key] Value\n }\n\n", + "span": { + "start": 971, + "end": 1023 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Missing line end after variant list" + ], + "span": { + "start": 1023, + "end": 1066 + } + }, + { + "type": "Junk", + "content": "missing-line-end =\n { $sel ->\n *[key] Value}\n", + "span": { + "start": 1067, + "end": 1122 + } + } + ], + "span": { + "start": 0, + "end": 1122 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/select_indent.spans.json b/fluent-syntax/tests/fixtures/select_indent.spans.json new file mode 100644 index 00000000..a2860971 --- /dev/null +++ b/fluent-syntax/tests/fixtures/select_indent.spans.json @@ -0,0 +1,1323 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "select-1tbs-inline", + "span": { + "start": 0, + "end": 18 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 24, + "end": 32 + } + }, + "span": { + "start": 23, + "end": 32 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 41, + "end": 44 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 46, + "end": 52 + } + } + ], + "span": { + "start": 46, + "end": 52 + } + }, + "default": true, + "span": { + "start": 39, + "end": 52 + } + } + ], + "span": { + "start": 23, + "end": 52 + } + }, + "span": { + "start": 21, + "end": 52 + } + } + ], + "span": { + "start": 21, + "end": 55 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 55 + } + }, + { + "type": "Message", + "id": { + "name": "select-1tbs-newline", + "span": { + "start": 55, + "end": 74 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 80, + "end": 88 + } + }, + "span": { + "start": 79, + "end": 88 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 97, + "end": 100 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 102, + "end": 108 + } + } + ], + "span": { + "start": 102, + "end": 108 + } + }, + "default": true, + "span": { + "start": 95, + "end": 108 + } + } + ], + "span": { + "start": 79, + "end": 108 + } + }, + "span": { + "start": 77, + "end": 108 + } + } + ], + "span": { + "start": 77, + "end": 111 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 55, + "end": 111 + } + }, + { + "type": "Message", + "id": { + "name": "select-1tbs-indent", + "span": { + "start": 111, + "end": 129 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 139, + "end": 147 + } + }, + "span": { + "start": 138, + "end": 147 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 156, + "end": 159 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 161, + "end": 167 + } + } + ], + "span": { + "start": 161, + "end": 167 + } + }, + "default": true, + "span": { + "start": 154, + "end": 167 + } + } + ], + "span": { + "start": 138, + "end": 167 + } + }, + "span": { + "start": 132, + "end": 167 + } + } + ], + "span": { + "start": 132, + "end": 170 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 111, + "end": 170 + } + }, + { + "type": "Message", + "id": { + "name": "select-allman-inline", + "span": { + "start": 170, + "end": 190 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 196, + "end": 204 + } + }, + "span": { + "start": 195, + "end": 204 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 213, + "end": 216 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 218, + "end": 224 + } + } + ], + "span": { + "start": 218, + "end": 224 + } + }, + "default": true, + "span": { + "start": 211, + "end": 224 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 229, + "end": 234 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Other", + "span": { + "start": 236, + "end": 242 + } + } + ], + "span": { + "start": 236, + "end": 242 + } + }, + "default": false, + "span": { + "start": 228, + "end": 242 + } + } + ], + "span": { + "start": 195, + "end": 242 + } + }, + "span": { + "start": 193, + "end": 242 + } + } + ], + "span": { + "start": 192, + "end": 245 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 170, + "end": 245 + } + }, + { + "type": "Message", + "id": { + "name": "select-allman-newline", + "span": { + "start": 245, + "end": 266 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 272, + "end": 280 + } + }, + "span": { + "start": 271, + "end": 280 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 289, + "end": 292 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 294, + "end": 300 + } + } + ], + "span": { + "start": 294, + "end": 300 + } + }, + "default": true, + "span": { + "start": 287, + "end": 300 + } + } + ], + "span": { + "start": 271, + "end": 300 + } + }, + "span": { + "start": 269, + "end": 300 + } + } + ], + "span": { + "start": 268, + "end": 303 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 245, + "end": 303 + } + }, + { + "type": "Message", + "id": { + "name": "select-allman-indent", + "span": { + "start": 303, + "end": 323 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 333, + "end": 341 + } + }, + "span": { + "start": 332, + "end": 341 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 350, + "end": 353 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 355, + "end": 361 + } + } + ], + "span": { + "start": 355, + "end": 361 + } + }, + "default": true, + "span": { + "start": 348, + "end": 361 + } + } + ], + "span": { + "start": 332, + "end": 361 + } + }, + "span": { + "start": 326, + "end": 361 + } + } + ], + "span": { + "start": 325, + "end": 364 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 303, + "end": 364 + } + }, + { + "type": "Message", + "id": { + "name": "select-gnu-inline", + "span": { + "start": 364, + "end": 381 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 390, + "end": 398 + } + }, + "span": { + "start": 389, + "end": 398 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 410, + "end": 413 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 415, + "end": 421 + } + } + ], + "span": { + "start": 415, + "end": 421 + } + }, + "default": true, + "span": { + "start": 408, + "end": 421 + } + } + ], + "span": { + "start": 389, + "end": 424 + } + }, + "span": { + "start": 387, + "end": 424 + } + } + ], + "span": { + "start": 383, + "end": 427 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 364, + "end": 427 + } + }, + { + "type": "Message", + "id": { + "name": "select-gnu-newline", + "span": { + "start": 427, + "end": 445 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 454, + "end": 462 + } + }, + "span": { + "start": 453, + "end": 462 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 474, + "end": 477 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 479, + "end": 485 + } + } + ], + "span": { + "start": 479, + "end": 485 + } + }, + "default": true, + "span": { + "start": 472, + "end": 485 + } + } + ], + "span": { + "start": 453, + "end": 488 + } + }, + "span": { + "start": 451, + "end": 488 + } + } + ], + "span": { + "start": 447, + "end": 491 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 427, + "end": 491 + } + }, + { + "type": "Message", + "id": { + "name": "select-gnu-indent", + "span": { + "start": 491, + "end": 508 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 524, + "end": 532 + } + }, + "span": { + "start": 523, + "end": 532 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 544, + "end": 547 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 549, + "end": 555 + } + } + ], + "span": { + "start": 549, + "end": 555 + } + }, + "default": true, + "span": { + "start": 542, + "end": 555 + } + } + ], + "span": { + "start": 523, + "end": 558 + } + }, + "span": { + "start": 514, + "end": 558 + } + } + ], + "span": { + "start": 510, + "end": 561 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 491, + "end": 561 + } + }, + { + "type": "Message", + "id": { + "name": "select-no-indent", + "span": { + "start": 561, + "end": 577 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 583, + "end": 591 + } + }, + "span": { + "start": 582, + "end": 591 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 597, + "end": 600 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 602, + "end": 608 + } + } + ], + "span": { + "start": 602, + "end": 608 + } + }, + "default": true, + "span": { + "start": 595, + "end": 608 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 609, + "end": 614 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Other", + "span": { + "start": 616, + "end": 622 + } + } + ], + "span": { + "start": 616, + "end": 622 + } + }, + "default": false, + "span": { + "start": 608, + "end": 622 + } + } + ], + "span": { + "start": 582, + "end": 622 + } + }, + "span": { + "start": 580, + "end": 622 + } + } + ], + "span": { + "start": 579, + "end": 625 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 561, + "end": 625 + } + }, + { + "type": "Message", + "id": { + "name": "select-no-indent-multiline", + "span": { + "start": 625, + "end": 651 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 657, + "end": 665 + } + }, + "span": { + "start": 656, + "end": 665 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 671, + "end": 674 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value\n", + "span": { + "start": 676, + "end": 682 + } + }, + { + "type": "TextElement", + "value": "Continued", + "span": { + "start": 689, + "end": 699 + } + } + ], + "span": { + "start": 676, + "end": 699 + } + }, + "default": true, + "span": { + "start": 669, + "end": 699 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 700, + "end": 705 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Other\n", + "span": { + "start": 711, + "end": 717 + } + }, + { + "type": "TextElement", + "value": "Multiline", + "span": { + "start": 721, + "end": 731 + } + } + ], + "span": { + "start": 706, + "end": 731 + } + }, + "default": false, + "span": { + "start": 699, + "end": 731 + } + } + ], + "span": { + "start": 656, + "end": 731 + } + }, + "span": { + "start": 654, + "end": 731 + } + } + ], + "span": { + "start": 653, + "end": 734 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 625, + "end": 734 + } + }, + { + "type": "Comment", + "content": [ + "ERROR (Multiline text must be indented)" + ], + "span": { + "start": 734, + "end": 775 + } + }, + { + "type": "Junk", + "content": "select-no-indent-multiline = { $selector ->\n *[key] Value\n", + "span": { + "start": 776, + "end": 836 + } + }, + { + "type": "Junk", + "content": "Continued without indent.\n}\n\n", + "span": { + "start": 836, + "end": 865 + } + }, + { + "type": "Message", + "id": { + "name": "select-flat", + "span": { + "start": 865, + "end": 876 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 882, + "end": 890 + } + }, + "span": { + "start": 881, + "end": 890 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 897, + "end": 900 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 903, + "end": 909 + } + } + ], + "span": { + "start": 903, + "end": 909 + } + }, + "default": true, + "span": { + "start": 894, + "end": 909 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 911, + "end": 916 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Other", + "span": { + "start": 919, + "end": 925 + } + } + ], + "span": { + "start": 919, + "end": 925 + } + }, + "default": false, + "span": { + "start": 909, + "end": 925 + } + } + ], + "span": { + "start": 881, + "end": 925 + } + }, + "span": { + "start": 879, + "end": 925 + } + } + ], + "span": { + "start": 878, + "end": 928 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 865, + "end": 928 + } + }, + { + "type": "Message", + "id": { + "name": "select-flat-with-trailing-spaces", + "span": { + "start": 960, + "end": 992 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "selector", + "span": { + "start": 1003, + "end": 1011 + } + }, + "span": { + "start": 1002, + "end": 1011 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 1033, + "end": 1036 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 1044, + "end": 1055 + } + } + ], + "span": { + "start": 1044, + "end": 1055 + } + }, + "default": true, + "span": { + "start": 1025, + "end": 1055 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 1062, + "end": 1067 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Other", + "span": { + "start": 1075, + "end": 1086 + } + } + ], + "span": { + "start": 1075, + "end": 1086 + } + }, + "default": false, + "span": { + "start": 1055, + "end": 1086 + } + } + ], + "span": { + "start": 1002, + "end": 1086 + } + }, + "span": { + "start": 995, + "end": 1086 + } + } + ], + "span": { + "start": 994, + "end": 1093 + } + }, + "attributes": [], + "comment": { + "content": [ + "Each line ends with 5 spaces." + ], + "span": { + "start": 928, + "end": 959 + } + }, + "span": { + "start": 960, + "end": 1093 + } + } + ], + "span": { + "start": 0, + "end": 1093 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/sparse_entries.spans.json b/fluent-syntax/tests/fixtures/sparse_entries.spans.json new file mode 100644 index 00000000..979c7468 --- /dev/null +++ b/fluent-syntax/tests/fixtures/sparse_entries.spans.json @@ -0,0 +1,332 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "key01", + "span": { + "start": 0, + "end": 5 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 14, + "end": 20 + } + } + ], + "span": { + "start": 7, + "end": 21 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 21 + } + }, + { + "type": "Message", + "id": { + "name": "key02", + "span": { + "start": 21, + "end": 26 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 36, + "end": 40 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute", + "span": { + "start": 43, + "end": 53 + } + } + ], + "span": { + "start": 43, + "end": 55 + } + }, + "span": { + "start": 54, + "end": 55 + } + } + ], + "comment": null, + "span": { + "start": 21, + "end": 55 + } + }, + { + "type": "Message", + "id": { + "name": "key03", + "span": { + "start": 55, + "end": 60 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value\n", + "span": { + "start": 67, + "end": 73 + } + }, + { + "type": "TextElement", + "value": "Continued\n", + "span": { + "start": 77, + "end": 87 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 87, + "end": 88 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 88, + "end": 89 + } + }, + { + "type": "TextElement", + "value": "Over multiple\n", + "span": { + "start": 93, + "end": 107 + } + }, + { + "type": "TextElement", + "value": "Lines", + "span": { + "start": 111, + "end": 117 + } + } + ], + "span": { + "start": 62, + "end": 120 + } + }, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 125, + "end": 129 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute", + "span": { + "start": 132, + "end": 142 + } + } + ], + "span": { + "start": 132, + "end": 144 + } + }, + "span": { + "start": 143, + "end": 144 + } + } + ], + "comment": null, + "span": { + "start": 55, + "end": 144 + } + }, + { + "type": "Message", + "id": { + "name": "key05", + "span": { + "start": 144, + "end": 149 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 172, + "end": 178 + } + } + ], + "span": { + "start": 172, + "end": 179 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 144, + "end": 179 + } + }, + { + "type": "Message", + "id": { + "name": "key06", + "span": { + "start": 179, + "end": 184 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 189, + "end": 190 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "one", + "span": { + "start": 206, + "end": 209 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "One", + "span": { + "start": 211, + "end": 215 + } + } + ], + "span": { + "start": 211, + "end": 219 + } + }, + "default": false, + "span": { + "start": 205, + "end": 219 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "two", + "span": { + "start": 229, + "end": 232 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Two", + "span": { + "start": 234, + "end": 238 + } + } + ], + "span": { + "start": 234, + "end": 241 + } + }, + "default": true, + "span": { + "start": 227, + "end": 241 + } + } + ], + "span": { + "start": 189, + "end": 245 + } + }, + "span": { + "start": 187, + "end": 245 + } + } + ], + "span": { + "start": 187, + "end": 247 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 179, + "end": 247 + } + } + ], + "span": { + "start": 0, + "end": 247 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/special_chars.spans.json b/fluent-syntax/tests/fixtures/special_chars.spans.json new file mode 100644 index 00000000..a2eb8ebd --- /dev/null +++ b/fluent-syntax/tests/fixtures/special_chars.spans.json @@ -0,0 +1,148 @@ +{ + "body": [ + { + "type": "GroupComment", + "content": [ + "OK" + ], + "span": { + "start": 0, + "end": 5 + } + }, + { + "type": "Message", + "id": { + "name": "bracket-inline", + "span": { + "start": 7, + "end": 21 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "[Value]", + "span": { + "start": 24, + "end": 32 + } + } + ], + "span": { + "start": 24, + "end": 32 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 7, + "end": 32 + } + }, + { + "type": "Message", + "id": { + "name": "dot-inline", + "span": { + "start": 32, + "end": 42 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": ".Value", + "span": { + "start": 45, + "end": 52 + } + } + ], + "span": { + "start": 45, + "end": 52 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 32, + "end": 52 + } + }, + { + "type": "Message", + "id": { + "name": "star-inline", + "span": { + "start": 52, + "end": 63 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "*Value", + "span": { + "start": 66, + "end": 73 + } + } + ], + "span": { + "start": 66, + "end": 74 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 52, + "end": 74 + } + }, + { + "type": "GroupComment", + "content": [ + "ERRORS" + ], + "span": { + "start": 74, + "end": 83 + } + }, + { + "type": "Junk", + "content": "bracket-newline =\n [Value]\n", + "span": { + "start": 85, + "end": 115 + } + }, + { + "type": "Junk", + "content": "dot-newline =\n .Value\n", + "span": { + "start": 115, + "end": 140 + } + }, + { + "type": "Junk", + "content": "star-newline =\n *Value\n", + "span": { + "start": 140, + "end": 166 + } + } + ], + "span": { + "start": 0, + "end": 166 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/tab.spans.json b/fluent-syntax/tests/fixtures/tab.spans.json new file mode 100644 index 00000000..e32f15b7 --- /dev/null +++ b/fluent-syntax/tests/fixtures/tab.spans.json @@ -0,0 +1,227 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "key01", + "span": { + "start": 40, + "end": 45 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "\tValue 01", + "span": { + "start": 47, + "end": 57 + } + } + ], + "span": { + "start": 47, + "end": 58 + } + }, + "attributes": [], + "comment": { + "content": [ + "OK (tab after = is part of the value)" + ], + "span": { + "start": 0, + "end": 39 + } + }, + "span": { + "start": 40, + "end": 58 + } + }, + { + "type": "Comment", + "content": [ + "Error (tab before =)" + ], + "span": { + "start": 58, + "end": 80 + } + }, + { + "type": "Junk", + "content": "key02\t= Value 02\n\n", + "span": { + "start": 81, + "end": 99 + } + }, + { + "type": "Comment", + "content": [ + "Error (tab is not a valid indent)" + ], + "span": { + "start": 99, + "end": 134 + } + }, + { + "type": "Junk", + "content": "key03 =\n\tThis line isn't properly indented.\n\n", + "span": { + "start": 135, + "end": 180 + } + }, + { + "type": "Message", + "id": { + "name": "key04", + "span": { + "start": 224, + "end": 229 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "This line is indented by 4 spaces,", + "span": { + "start": 236, + "end": 271 + } + } + ], + "span": { + "start": 231, + "end": 271 + } + }, + "attributes": [], + "comment": { + "content": [ + "Partial Error (tab is not a valid indent)" + ], + "span": { + "start": 180, + "end": 223 + } + }, + "span": { + "start": 224, + "end": 271 + } + }, + { + "type": "Junk", + "content": "\twhereas this line by 1 tab.\n\n", + "span": { + "start": 271, + "end": 301 + } + }, + { + "type": "Message", + "id": { + "name": "key05", + "span": { + "start": 330, + "end": 335 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "\t", + "span": { + "start": 338, + "end": 340 + } + } + ], + "span": { + "start": 338, + "end": 341 + } + }, + "attributes": [], + "comment": { + "content": [ + "OK (value is a single tab)" + ], + "span": { + "start": 301, + "end": 329 + } + }, + "span": { + "start": 330, + "end": 341 + } + }, + { + "type": "Message", + "id": { + "name": "key06", + "span": { + "start": 376, + "end": 381 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 387, + "end": 391 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "\t\t", + "span": { + "start": 394, + "end": 397 + } + } + ], + "span": { + "start": 394, + "end": 397 + } + }, + "span": { + "start": 396, + "end": 397 + } + } + ], + "comment": { + "content": [ + "OK (attribute value is two tabs)" + ], + "span": { + "start": 341, + "end": 375 + } + }, + "span": { + "start": 376, + "end": 397 + } + } + ], + "span": { + "start": 0, + "end": 397 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/term_parameters.spans.json b/fluent-syntax/tests/fixtures/term_parameters.spans.json new file mode 100644 index 00000000..ea8bcd7e --- /dev/null +++ b/fluent-syntax/tests/fixtures/term_parameters.spans.json @@ -0,0 +1,406 @@ +{ + "body": [ + { + "type": "Term", + "id": { + "name": "term", + "span": { + "start": 1, + "end": 5 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "arg", + "span": { + "start": 11, + "end": 14 + } + }, + "span": { + "start": 10, + "end": 14 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 23, + "end": 26 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 28, + "end": 34 + } + } + ], + "span": { + "start": 28, + "end": 34 + } + }, + "default": true, + "span": { + "start": 21, + "end": 34 + } + } + ], + "span": { + "start": 10, + "end": 34 + } + }, + "span": { + "start": 8, + "end": 34 + } + } + ], + "span": { + "start": 8, + "end": 37 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 37 + } + }, + { + "type": "Message", + "id": { + "name": "key01", + "span": { + "start": 37, + "end": 42 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "term", + "span": { + "start": 48, + "end": 52 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 47, + "end": 53 + } + }, + { + "start": 47, + "end": 53 + } + ], + "span": { + "start": 45, + "end": 53 + } + } + ], + "span": { + "start": 45, + "end": 55 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 37, + "end": 55 + } + }, + { + "type": "Message", + "id": { + "name": "key02", + "span": { + "start": 55, + "end": 60 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "term", + "span": { + "start": 66, + "end": 70 + } + }, + "attribute": null, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 71, + "end": 73 + } + }, + "span": { + "start": 65, + "end": 73 + } + }, + { + "start": 65, + "end": 74 + } + ], + "span": { + "start": 63, + "end": 74 + } + } + ], + "span": { + "start": 63, + "end": 76 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 55, + "end": 76 + } + }, + { + "type": "Message", + "id": { + "name": "key03", + "span": { + "start": 76, + "end": 81 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "term", + "span": { + "start": 87, + "end": 91 + } + }, + "attribute": null, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "arg", + "span": { + "start": 92, + "end": 95 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 97, + "end": 98 + } + }, + "span": { + "start": 92, + "end": 98 + } + } + ], + "span": { + "start": 91, + "end": 99 + } + }, + "span": { + "start": 86, + "end": 99 + } + }, + { + "start": 86, + "end": 100 + } + ], + "span": { + "start": 84, + "end": 100 + } + } + ], + "span": { + "start": 84, + "end": 102 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 76, + "end": 102 + } + }, + { + "type": "Message", + "id": { + "name": "key04", + "span": { + "start": 102, + "end": 107 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "term", + "span": { + "start": 113, + "end": 117 + } + }, + "attribute": null, + "arguments": { + "type": "CallArguments", + "positional": [ + { + "type": "StringLiteral", + "value": "positional", + "span": { + "start": 118, + "end": 130 + } + } + ], + "named": [ + { + "type": "NamedArgument", + "name": { + "name": "narg1", + "span": { + "start": 132, + "end": 137 + } + }, + "value": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 139, + "end": 140 + } + }, + "span": { + "start": 132, + "end": 140 + } + }, + { + "type": "NamedArgument", + "name": { + "name": "narg2", + "span": { + "start": 142, + "end": 147 + } + }, + "value": { + "type": "NumberLiteral", + "value": "2", + "span": { + "start": 149, + "end": 150 + } + }, + "span": { + "start": 142, + "end": 150 + } + } + ], + "span": { + "start": 117, + "end": 151 + } + }, + "span": { + "start": 112, + "end": 151 + } + }, + { + "start": 112, + "end": 152 + } + ], + "span": { + "start": 110, + "end": 152 + } + } + ], + "span": { + "start": 110, + "end": 154 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 102, + "end": 154 + } + } + ], + "span": { + "start": 0, + "end": 154 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/terms.spans.json b/fluent-syntax/tests/fixtures/terms.spans.json new file mode 100644 index 00000000..64ec5563 --- /dev/null +++ b/fluent-syntax/tests/fixtures/terms.spans.json @@ -0,0 +1,331 @@ +{ + "body": [ + { + "type": "Term", + "id": { + "name": "term01", + "span": { + "start": 1, + "end": 7 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 10, + "end": 16 + } + } + ], + "span": { + "start": 10, + "end": 16 + } + }, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 21, + "end": 25 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute", + "span": { + "start": 28, + "end": 38 + } + } + ], + "span": { + "start": 28, + "end": 39 + } + }, + "span": { + "start": 38, + "end": 39 + } + } + ], + "comment": null, + "span": { + "start": 0, + "end": 39 + } + }, + { + "type": "Term", + "id": { + "name": "term02", + "span": { + "start": 40, + "end": 46 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "", + "span": { + "start": 50, + "end": 52 + } + }, + { + "start": 50, + "end": 52 + } + ], + "span": { + "start": 49, + "end": 52 + } + } + ], + "span": { + "start": 49, + "end": 55 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 39, + "end": 55 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Missing value" + ], + "span": { + "start": 55, + "end": 75 + } + }, + { + "type": "Junk", + "content": "-term03 =\n .attr = Attribute\n\n", + "span": { + "start": 76, + "end": 109 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Missing value", + " < whitespace >" + ], + "span": { + "start": 109, + "end": 155 + } + }, + { + "type": "Junk", + "content": "-term04 = \n .attr1 = Attribute 1\n\n", + "span": { + "start": 156, + "end": 208 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Missing value" + ], + "span": { + "start": 208, + "end": 228 + } + }, + { + "type": "Junk", + "content": "-term05 =\n\n", + "span": { + "start": 229, + "end": 240 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Missing value", + " < whitespace >" + ], + "span": { + "start": 240, + "end": 286 + } + }, + { + "type": "Junk", + "content": "-term06 = \n\n", + "span": { + "start": 287, + "end": 314 + } + }, + { + "type": "Comment", + "content": [ + "JUNK Missing =" + ], + "span": { + "start": 314, + "end": 330 + } + }, + { + "type": "Junk", + "content": "-term07\n\n", + "span": { + "start": 331, + "end": 340 + } + }, + { + "type": "Term", + "id": { + "name": "term08", + "span": { + "start": 341, + "end": 347 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 348, + "end": 354 + } + } + ], + "span": { + "start": 348, + "end": 354 + } + }, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 359, + "end": 363 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute", + "span": { + "start": 364, + "end": 374 + } + } + ], + "span": { + "start": 364, + "end": 375 + } + }, + "span": { + "start": 374, + "end": 375 + } + } + ], + "comment": null, + "span": { + "start": 340, + "end": 375 + } + }, + { + "type": "Term", + "id": { + "name": "term09", + "span": { + "start": 376, + "end": 382 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Value", + "span": { + "start": 388, + "end": 394 + } + } + ], + "span": { + "start": 388, + "end": 394 + } + }, + "attributes": [ + { + "id": { + "name": "attr", + "span": { + "start": 399, + "end": 403 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Attribute", + "span": { + "start": 409, + "end": 419 + } + } + ], + "span": { + "start": 409, + "end": 419 + } + }, + "span": { + "start": 418, + "end": 419 + } + } + ], + "comment": null, + "span": { + "start": 375, + "end": 419 + } + } + ], + "span": { + "start": 0, + "end": 419 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/variables.spans.json b/fluent-syntax/tests/fixtures/variables.spans.json new file mode 100644 index 00000000..2e1ffe3b --- /dev/null +++ b/fluent-syntax/tests/fixtures/variables.spans.json @@ -0,0 +1,276 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "key01", + "span": { + "start": 0, + "end": 5 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "var", + "span": { + "start": 10, + "end": 13 + } + }, + "span": { + "start": 9, + "end": 13 + } + }, + { + "start": 9, + "end": 13 + } + ], + "span": { + "start": 8, + "end": 13 + } + } + ], + "span": { + "start": 8, + "end": 15 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 15 + } + }, + { + "type": "Message", + "id": { + "name": "key02", + "span": { + "start": 15, + "end": 20 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "var", + "span": { + "start": 28, + "end": 31 + } + }, + "span": { + "start": 27, + "end": 31 + } + }, + { + "start": 27, + "end": 34 + } + ], + "span": { + "start": 23, + "end": 34 + } + } + ], + "span": { + "start": 23, + "end": 36 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 15, + "end": 36 + } + }, + { + "type": "Message", + "id": { + "name": "key03", + "span": { + "start": 36, + "end": 41 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "var", + "span": { + "start": 51, + "end": 54 + } + }, + "span": { + "start": 50, + "end": 54 + } + }, + { + "start": 50, + "end": 55 + } + ], + "span": { + "start": 44, + "end": 55 + } + } + ], + "span": { + "start": 44, + "end": 57 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 36, + "end": 57 + } + }, + { + "type": "Message", + "id": { + "name": "key04", + "span": { + "start": 57, + "end": 62 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "var", + "span": { + "start": 68, + "end": 71 + } + }, + "span": { + "start": 67, + "end": 71 + } + }, + { + "start": 67, + "end": 71 + } + ], + "span": { + "start": 65, + "end": 71 + } + } + ], + "span": { + "start": 65, + "end": 75 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 57, + "end": 75 + } + }, + { + "type": "GroupComment", + "content": [ + "Errors" + ], + "span": { + "start": 75, + "end": 84 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Missing variable identifier" + ], + "span": { + "start": 86, + "end": 121 + } + }, + { + "type": "Junk", + "content": "err01 = {$}\n", + "span": { + "start": 122, + "end": 134 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Double $$" + ], + "span": { + "start": 134, + "end": 151 + } + }, + { + "type": "Junk", + "content": "err02 = {$$var}\n", + "span": { + "start": 152, + "end": 168 + } + }, + { + "type": "Comment", + "content": [ + "ERROR Invalid first char of the identifier" + ], + "span": { + "start": 168, + "end": 212 + } + }, + { + "type": "Junk", + "content": "err03 = {$-var}\n", + "span": { + "start": 213, + "end": 229 + } + } + ], + "span": { + "start": 0, + "end": 229 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/variant_keys.spans.json b/fluent-syntax/tests/fixtures/variant_keys.spans.json new file mode 100644 index 00000000..18100134 --- /dev/null +++ b/fluent-syntax/tests/fixtures/variant_keys.spans.json @@ -0,0 +1,402 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "simple-identifier", + "span": { + "start": 0, + "end": 17 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "sel", + "span": { + "start": 27, + "end": 30 + } + }, + "span": { + "start": 26, + "end": 30 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 43, + "end": 46 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "value", + "span": { + "start": 48, + "end": 54 + } + } + ], + "span": { + "start": 48, + "end": 54 + } + }, + "default": true, + "span": { + "start": 41, + "end": 54 + } + } + ], + "span": { + "start": 26, + "end": 58 + } + }, + "span": { + "start": 24, + "end": 58 + } + } + ], + "span": { + "start": 19, + "end": 61 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 0, + "end": 61 + } + }, + { + "type": "Message", + "id": { + "name": "identifier-surrounded-by-whitespace", + "span": { + "start": 61, + "end": 96 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "sel", + "span": { + "start": 106, + "end": 109 + } + }, + "span": { + "start": 105, + "end": 109 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "key", + "span": { + "start": 127, + "end": 130 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "value", + "span": { + "start": 137, + "end": 143 + } + } + ], + "span": { + "start": 137, + "end": 143 + } + }, + "default": true, + "span": { + "start": 120, + "end": 143 + } + } + ], + "span": { + "start": 105, + "end": 147 + } + }, + "span": { + "start": 103, + "end": 147 + } + } + ], + "span": { + "start": 98, + "end": 150 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 61, + "end": 150 + } + }, + { + "type": "Message", + "id": { + "name": "int-number", + "span": { + "start": 150, + "end": 160 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "sel", + "span": { + "start": 170, + "end": 173 + } + }, + "span": { + "start": 169, + "end": 173 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "NumberLiteral", + "value": "1", + "span": { + "start": 186, + "end": 187 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "value", + "span": { + "start": 189, + "end": 195 + } + } + ], + "span": { + "start": 189, + "end": 195 + } + }, + "default": true, + "span": { + "start": 184, + "end": 195 + } + } + ], + "span": { + "start": 169, + "end": 199 + } + }, + "span": { + "start": 167, + "end": 199 + } + } + ], + "span": { + "start": 162, + "end": 202 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 150, + "end": 202 + } + }, + { + "type": "Message", + "id": { + "name": "float-number", + "span": { + "start": 202, + "end": 214 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "sel", + "span": { + "start": 224, + "end": 227 + } + }, + "span": { + "start": 223, + "end": 227 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "NumberLiteral", + "value": "3.14", + "span": { + "start": 240, + "end": 244 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "value", + "span": { + "start": 246, + "end": 252 + } + } + ], + "span": { + "start": 246, + "end": 252 + } + }, + "default": true, + "span": { + "start": 238, + "end": 252 + } + } + ], + "span": { + "start": 223, + "end": 256 + } + }, + "span": { + "start": 221, + "end": 256 + } + } + ], + "span": { + "start": 216, + "end": 259 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 202, + "end": 259 + } + }, + { + "type": "Comment", + "content": [ + "ERROR" + ], + "span": { + "start": 259, + "end": 266 + } + }, + { + "type": "Junk", + "content": "invalid-identifier =\n { $sel ->\n *[two words] value\n }\n\n", + "span": { + "start": 267, + "end": 335 + } + }, + { + "type": "Comment", + "content": [ + "ERROR" + ], + "span": { + "start": 335, + "end": 342 + } + }, + { + "type": "Junk", + "content": "invalid-int =\n { $sel ->\n *[1 apple] value\n }\n\n", + "span": { + "start": 343, + "end": 402 + } + }, + { + "type": "Comment", + "content": [ + "ERROR" + ], + "span": { + "start": 402, + "end": 409 + } + }, + { + "type": "Junk", + "content": "invalid-int =\n { $sel ->\n *[3.14 apples] value\n }\n", + "span": { + "start": 410, + "end": 472 + } + } + ], + "span": { + "start": 0, + "end": 472 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/whitespace_in_value.spans.json b/fluent-syntax/tests/fixtures/whitespace_in_value.spans.json new file mode 100644 index 00000000..831df237 --- /dev/null +++ b/fluent-syntax/tests/fixtures/whitespace_in_value.spans.json @@ -0,0 +1,104 @@ +{ + "body": [ + { + "type": "Message", + "id": { + "name": "key", + "span": { + "start": 56, + "end": 59 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "first line\n", + "span": { + "start": 64, + "end": 75 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 75, + "end": 76 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 76, + "end": 77 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 79, + "end": 80 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 82, + "end": 83 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 83, + "end": 84 + } + }, + { + "type": "TextElement", + "value": "\n", + "span": { + "start": 84, + "end": 85 + } + }, + { + "type": "TextElement", + "value": "last line", + "span": { + "start": 87, + "end": 97 + } + } + ], + "span": { + "start": 61, + "end": 97 + } + }, + "attributes": [], + "comment": { + "content": [ + "Caution, lines 6 and 7 contain white-space-only lines" + ], + "span": { + "start": 0, + "end": 55 + } + }, + "span": { + "start": 56, + "end": 97 + } + } + ], + "span": { + "start": 0, + "end": 97 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/zero_length.spans.json b/fluent-syntax/tests/fixtures/zero_length.spans.json new file mode 100644 index 00000000..80b9c4ce --- /dev/null +++ b/fluent-syntax/tests/fixtures/zero_length.spans.json @@ -0,0 +1,7 @@ +{ + "body": [], + "span": { + "start": 0, + "end": 0 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/helper/mod.rs b/fluent-syntax/tests/helper/mod.rs index cb981e9a..e6e87bd6 100644 --- a/fluent-syntax/tests/helper/mod.rs +++ b/fluent-syntax/tests/helper/mod.rs @@ -13,7 +13,7 @@ fn adapt_pattern(pattern: &mut ast::Pattern, crlf: bool) { let mut elements = vec![]; for element in &pattern.elements { match element { - ast::PatternElement::TextElement { value, .. } => { + ast::PatternElement::TextElement { value, #[cfg(feature = "spans")] span } => { let mut start = 0; let len = value.len(); for (i, b) in value.as_bytes().iter().enumerate() { @@ -25,14 +25,14 @@ fn adapt_pattern(pattern: &mut ast::Pattern, crlf: bool) { elements.push(ast::PatternElement::TextElement { value, #[cfg(feature = "spans")] - span: ast::Span(start..i), + span: span.clone(), }); } elements.push(ast::PatternElement::TextElement { value: "\n".to_string(), #[cfg(feature = "spans")] - span: ast::Span(i..i + 1), + span: span.clone(), }); } else { let chunk = &value.as_bytes()[start..=i]; @@ -40,7 +40,7 @@ fn adapt_pattern(pattern: &mut ast::Pattern, crlf: bool) { elements.push(ast::PatternElement::TextElement { value, #[cfg(feature = "spans")] - span: ast::Span(start..i + 1), + span: span.clone(), }); } start = i + 1; @@ -53,7 +53,7 @@ fn adapt_pattern(pattern: &mut ast::Pattern, crlf: bool) { elements.push(ast::PatternElement::TextElement { value, #[cfg(feature = "spans")] - span: ast::Span(start..len), + span: span.clone(), }); } } diff --git a/fluent-syntax/tests/parser_fixtures.rs b/fluent-syntax/tests/parser_fixtures.rs index a067d38e..6c63e7b5 100644 --- a/fluent-syntax/tests/parser_fixtures.rs +++ b/fluent-syntax/tests/parser_fixtures.rs @@ -25,7 +25,11 @@ fn parse_fixtures_compare() { let path = p.to_str().expect("Can't print path"); let is_crlf = path.contains("crlf"); + #[cfg(feature = "spans")] + let reference_path = path.replace(".ftl", ".spans.json"); + #[cfg(not(feature = "spans"))] let reference_path = path.replace(".ftl", ".json"); + let reference_file = read_file(&reference_path, true).unwrap(); let ftl_file = read_file(path, false).unwrap(); @@ -67,6 +71,12 @@ fn parse_bench_fixtures() { let path = p.to_str().expect("Can't print path"); let file_name = p.file_name().unwrap().to_str().unwrap(); + #[cfg(feature = "spans")] + let reference_path = format!( + "./tests/fixtures/benches/{}", + file_name.replace(".ftl", ".spans.json") + ); + #[cfg(not(feature = "spans"))] let reference_path = format!( "./tests/fixtures/benches/{}", file_name.replace(".ftl", ".json") From adae4a04e491846b5bd22b605c669812473395a4 Mon Sep 17 00:00:00 2001 From: Ertanic Date: Fri, 23 May 2025 09:44:20 +0300 Subject: [PATCH 11/11] Fix parse_bench_fixtures test --- .../contexts/browser/appmenu.spans.json | 270 + .../benches/contexts/browser/brand.spans.json | 239 + .../contexts/browser/brandings.spans.json | 290 + .../contexts/browser/browser.spans.json | 5045 +++ .../browser/browserContext.spans.json | 7109 +++++ .../contexts/browser/browserSets.spans.json | 2874 ++ .../contexts/browser/interventions.spans.json | 692 + .../contexts/browser/menubar.spans.json | 6073 ++++ .../browser/protectionsPanel.spans.json | 92 + .../contexts/browser/sync-brand.spans.json | 134 + .../contexts/browser/textActions.spans.json | 834 + .../preferences/aboutDialog.spans.json | 1353 + .../preferences/blocklists.spans.json | 639 + .../contexts/preferences/brand.spans.json | 239 + .../contexts/preferences/brandings.spans.json | 290 + .../preferences/certManager.spans.json | 5554 ++++ .../preferences/clearSiteData.spans.json | 920 + .../contexts/preferences/colors.spans.json | 904 + .../preferences/connection.spans.json | 2198 ++ .../preferences/deviceManager.spans.json | 2192 ++ .../contexts/preferences/fonts.spans.json | 3247 ++ .../contexts/preferences/history.spans.json | 576 + .../contexts/preferences/languages.spans.json | 1265 + .../preferences/permissions.spans.json | 3386 ++ .../preferences/preferences.spans.json | 25803 ++++++++++++++++ .../contexts/preferences/sanitize.spans.json | 1654 + .../preferences/selectBookmark.spans.json | 128 + .../preferences/siteDataSettings.spans.json | 1224 + .../preferences/sync-brand.spans.json | 134 + .../tests/fixtures/benches/menubar.spans.json | 7195 +++++ .../fixtures/benches/preferences.spans.json | 21010 +++++++++++++ .../tests/fixtures/benches/simple.spans.json | 3218 ++ fluent-syntax/tests/parser_fixtures.rs | 7 + 33 files changed, 106788 insertions(+) create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/appmenu.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/brand.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/brandings.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/browser.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/browserContext.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/browserSets.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/interventions.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/menubar.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/protectionsPanel.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/sync-brand.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/browser/textActions.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/aboutDialog.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/blocklists.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/brand.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/brandings.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/certManager.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/clearSiteData.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/colors.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/connection.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/deviceManager.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/fonts.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/history.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/languages.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/permissions.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/preferences.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/sanitize.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/selectBookmark.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/siteDataSettings.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/contexts/preferences/sync-brand.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/menubar.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/preferences.spans.json create mode 100644 fluent-syntax/tests/fixtures/benches/simple.spans.json diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/appmenu.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/appmenu.spans.json new file mode 100644 index 00000000..2dce23f8 --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/appmenu.spans.json @@ -0,0 +1,270 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "GroupComment", + "content": [ + "App Menu" + ], + "span": { + "start": 200, + "end": 211 + } + }, + { + "type": "Message", + "id": { + "name": "appmenuitem-protection-report-title", + "span": { + "start": 213, + "end": 248 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Privacy Protections", + "span": { + "start": 251, + "end": 271 + } + } + ], + "span": { + "start": 251, + "end": 271 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 213, + "end": 271 + } + }, + { + "type": "Message", + "id": { + "name": "appmenuitem-protection-report-tooltip", + "span": { + "start": 271, + "end": 308 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 316, + "end": 327 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Go to your privacy report", + "span": { + "start": 330, + "end": 356 + } + } + ], + "span": { + "start": 330, + "end": 357 + } + }, + "span": { + "start": 356, + "end": 357 + } + } + ], + "comment": null, + "span": { + "start": 271, + "end": 357 + } + }, + { + "type": "GroupComment", + "content": [ + "Zoom Controls" + ], + "span": { + "start": 357, + "end": 373 + } + }, + { + "type": "Message", + "id": { + "name": "appmenuitem-zoom-enlarge", + "span": { + "start": 375, + "end": 399 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 405, + "end": 410 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Zoom in", + "span": { + "start": 413, + "end": 421 + } + } + ], + "span": { + "start": 413, + "end": 421 + } + }, + "span": { + "start": 420, + "end": 421 + } + } + ], + "comment": null, + "span": { + "start": 375, + "end": 421 + } + }, + { + "type": "Message", + "id": { + "name": "appmenuitem-zoom-reduce", + "span": { + "start": 421, + "end": 444 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 450, + "end": 455 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Zoom out", + "span": { + "start": 458, + "end": 467 + } + } + ], + "span": { + "start": 458, + "end": 468 + } + }, + "span": { + "start": 467, + "end": 468 + } + } + ], + "comment": null, + "span": { + "start": 421, + "end": 468 + } + }, + { + "type": "GroupComment", + "content": [ + "Firefox Account toolbar button and Sync panel in App menu." + ], + "span": { + "start": 468, + "end": 529 + } + }, + { + "type": "Message", + "id": { + "name": "fxa-toolbar-sync-now", + "span": { + "start": 531, + "end": 551 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 559, + "end": 564 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Sync Now", + "span": { + "start": 567, + "end": 576 + } + } + ], + "span": { + "start": 567, + "end": 576 + } + }, + "span": { + "start": 575, + "end": 576 + } + } + ], + "comment": null, + "span": { + "start": 531, + "end": 576 + } + } + ], + "span": { + "start": 0, + "end": 576 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/brand.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/brand.spans.json new file mode 100644 index 00000000..89b0710d --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/brand.spans.json @@ -0,0 +1,239 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "GroupComment", + "content": [ + "Firefox Brand", + "", + "Firefox must be treated as a brand, and kept in English.", + "It cannot be:", + "- Declined to adapt to grammatical case.", + "- Transliterated.", + "- Translated.", + "", + "Reference: https://www.mozilla.org/styleguide/communications/translation/" + ], + "span": { + "start": 200, + "end": 458 + } + }, + { + "type": "Term", + "id": { + "name": "brand-shorter-name", + "span": { + "start": 461, + "end": 479 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Firefox", + "span": { + "start": 482, + "end": 490 + } + } + ], + "span": { + "start": 482, + "end": 490 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 460, + "end": 490 + } + }, + { + "type": "Term", + "id": { + "name": "brand-short-name", + "span": { + "start": 491, + "end": 507 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Firefox", + "span": { + "start": 510, + "end": 518 + } + } + ], + "span": { + "start": 510, + "end": 518 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 490, + "end": 518 + } + }, + { + "type": "Term", + "id": { + "name": "brand-full-name", + "span": { + "start": 519, + "end": 534 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Mozilla Firefox", + "span": { + "start": 537, + "end": 553 + } + } + ], + "span": { + "start": 537, + "end": 553 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 518, + "end": 553 + } + }, + { + "type": "Term", + "id": { + "name": "brand-product-name", + "span": { + "start": 696, + "end": 714 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Firefox", + "span": { + "start": 717, + "end": 725 + } + } + ], + "span": { + "start": 717, + "end": 725 + } + }, + "attributes": [], + "comment": { + "content": [ + "This brand name can be used in messages where the product name needs to", + "remain unchanged across different versions (Nightly, Beta, etc.)." + ], + "span": { + "start": 553, + "end": 694 + } + }, + "span": { + "start": 695, + "end": 725 + } + }, + { + "type": "Term", + "id": { + "name": "vendor-short-name", + "span": { + "start": 726, + "end": 743 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Mozilla", + "span": { + "start": 746, + "end": 754 + } + } + ], + "span": { + "start": 746, + "end": 754 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 725, + "end": 754 + } + }, + { + "type": "Message", + "id": { + "name": "trademarkInfo", + "span": { + "start": 754, + "end": 767 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Firefox and the Firefox logos are trademarks of the Mozilla Foundation.", + "span": { + "start": 770, + "end": 842 + } + } + ], + "span": { + "start": 770, + "end": 842 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 754, + "end": 842 + } + } + ], + "span": { + "start": 0, + "end": 842 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/brandings.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/brandings.spans.json new file mode 100644 index 00000000..5202dc6b --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/brandings.spans.json @@ -0,0 +1,290 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "GroupComment", + "content": [ + "The following feature names must be treated as a brand, and kept in English.", + "They cannot be:", + "- Declined to adapt to grammatical case.", + "- Transliterated.", + "- Translated." + ], + "span": { + "start": 200, + "end": 380 + } + }, + { + "type": "Term", + "id": { + "name": "facebook-container-brand-name", + "span": { + "start": 383, + "end": 412 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Facebook Container", + "span": { + "start": 415, + "end": 434 + } + } + ], + "span": { + "start": 415, + "end": 434 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 382, + "end": 434 + } + }, + { + "type": "Term", + "id": { + "name": "lockwise-brand-name", + "span": { + "start": 435, + "end": 454 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Firefox Lockwise", + "span": { + "start": 457, + "end": 474 + } + } + ], + "span": { + "start": 457, + "end": 474 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 434, + "end": 474 + } + }, + { + "type": "Term", + "id": { + "name": "lockwise-brand-short-name", + "span": { + "start": 475, + "end": 500 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Lockwise", + "span": { + "start": 503, + "end": 512 + } + } + ], + "span": { + "start": 503, + "end": 512 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 474, + "end": 512 + } + }, + { + "type": "Term", + "id": { + "name": "monitor-brand-name", + "span": { + "start": 513, + "end": 531 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Firefox Monitor", + "span": { + "start": 534, + "end": 550 + } + } + ], + "span": { + "start": 534, + "end": 550 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 512, + "end": 550 + } + }, + { + "type": "Term", + "id": { + "name": "monitor-brand-short-name", + "span": { + "start": 551, + "end": 575 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Monitor", + "span": { + "start": 578, + "end": 586 + } + } + ], + "span": { + "start": 578, + "end": 586 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 550, + "end": 586 + } + }, + { + "type": "Term", + "id": { + "name": "pocket-brand-name", + "span": { + "start": 587, + "end": 604 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Pocket", + "span": { + "start": 607, + "end": 614 + } + } + ], + "span": { + "start": 607, + "end": 614 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 586, + "end": 614 + } + }, + { + "type": "Term", + "id": { + "name": "send-brand-name", + "span": { + "start": 615, + "end": 630 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Firefox Send", + "span": { + "start": 633, + "end": 646 + } + } + ], + "span": { + "start": 633, + "end": 646 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 614, + "end": 646 + } + }, + { + "type": "Term", + "id": { + "name": "screenshots-brand-name", + "span": { + "start": 647, + "end": 669 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Firefox Screenshots", + "span": { + "start": 672, + "end": 692 + } + } + ], + "span": { + "start": 672, + "end": 692 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 646, + "end": 692 + } + } + ], + "span": { + "start": 0, + "end": 692 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/browser.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/browser.spans.json new file mode 100644 index 00000000..7de7b016 --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/browser.spans.json @@ -0,0 +1,5045 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "Message", + "id": { + "name": "browser-main-window-title", + "span": { + "start": 547, + "end": 572 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "VariableReference", + "id": { + "name": "mode", + "span": { + "start": 578, + "end": 582 + } + }, + "span": { + "start": 577, + "end": 582 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "private", + "span": { + "start": 595, + "end": 602 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-full-name", + "span": { + "start": 607, + "end": 622 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 606, + "end": 623 + } + }, + { + "start": 606, + "end": 623 + } + ], + "span": { + "start": 604, + "end": 623 + } + }, + { + "type": "TextElement", + "value": " (Private Browsing)", + "span": { + "start": 624, + "end": 644 + } + } + ], + "span": { + "start": 604, + "end": 644 + } + }, + "default": false, + "span": { + "start": 594, + "end": 644 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "default", + "span": { + "start": 653, + "end": 660 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-full-name", + "span": { + "start": 665, + "end": 680 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 664, + "end": 681 + } + }, + { + "start": 664, + "end": 681 + } + ], + "span": { + "start": 662, + "end": 681 + } + } + ], + "span": { + "start": 662, + "end": 683 + } + }, + "default": true, + "span": { + "start": 651, + "end": 683 + } + } + ], + "span": { + "start": 577, + "end": 687 + } + }, + "span": { + "start": 575, + "end": 687 + } + } + ], + "span": { + "start": 575, + "end": 690 + } + }, + "attributes": [], + "comment": { + "content": [ + "This is the default window title in case there is no content", + "title to be displayed.", + "", + "Depending on the $mode, the string will look like this (in en-US):", + "", + "\"default\" - \"Mozilla Firefox\"", + "\"private\" - \"Mozilla Firefox (Private Browsing)\"", + "", + "Variables", + " $mode (String) - \"private\" in case of a private browsing mode, \"default\" otherwise." + ], + "span": { + "start": 201, + "end": 546 + } + }, + "span": { + "start": 547, + "end": 690 + } + }, + { + "type": "GroupComment", + "content": [ + "This is the default window title in case there is content", + "title to be displayed.", + "", + "On macOS the title doesn't include the brand name, on all other", + "platforms it does.", + "", + "For example, in private mode on Windows, the title will be:", + "\"Example Title - Mozilla Firefox (Private Browsing)\"", + "", + "while on macOS in default mode it will be:", + "\"Example Title\"", + "", + "Variables", + " $title (String) - Content title string." + ], + "span": { + "start": 690, + "end": 1119 + } + }, + { + "type": "Message", + "id": { + "name": "browser-main-window-content-title-default", + "span": { + "start": 1121, + "end": 1162 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "PLATFORM", + "span": { + "start": 1167, + "end": 1175 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 1175, + "end": 1177 + } + }, + "span": { + "start": 1167, + "end": 1177 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "macos", + "span": { + "start": 1186, + "end": 1191 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "title", + "span": { + "start": 1196, + "end": 1201 + } + }, + "span": { + "start": 1195, + "end": 1201 + } + }, + { + "start": 1195, + "end": 1202 + } + ], + "span": { + "start": 1193, + "end": 1202 + } + } + ], + "span": { + "start": 1193, + "end": 1204 + } + }, + "default": false, + "span": { + "start": 1185, + "end": 1204 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 1209, + "end": 1214 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "title", + "span": { + "start": 1219, + "end": 1224 + } + }, + "span": { + "start": 1218, + "end": 1224 + } + }, + { + "start": 1218, + "end": 1225 + } + ], + "span": { + "start": 1216, + "end": 1225 + } + }, + { + "type": "TextElement", + "value": " - ", + "span": { + "start": 1226, + "end": 1229 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-full-name", + "span": { + "start": 1232, + "end": 1247 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 1231, + "end": 1248 + } + }, + { + "start": 1231, + "end": 1248 + } + ], + "span": { + "start": 1229, + "end": 1248 + } + } + ], + "span": { + "start": 1216, + "end": 1250 + } + }, + "default": true, + "span": { + "start": 1207, + "end": 1250 + } + } + ], + "span": { + "start": 1167, + "end": 1250 + } + }, + "span": { + "start": 1165, + "end": 1250 + } + } + ], + "span": { + "start": 1165, + "end": 1253 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1121, + "end": 1253 + } + }, + { + "type": "Message", + "id": { + "name": "browser-main-window-content-title-private", + "span": { + "start": 1253, + "end": 1294 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "PLATFORM", + "span": { + "start": 1299, + "end": 1307 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 1307, + "end": 1309 + } + }, + "span": { + "start": 1299, + "end": 1309 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "macos", + "span": { + "start": 1318, + "end": 1323 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "title", + "span": { + "start": 1328, + "end": 1333 + } + }, + "span": { + "start": 1327, + "end": 1333 + } + }, + { + "start": 1327, + "end": 1334 + } + ], + "span": { + "start": 1325, + "end": 1334 + } + }, + { + "type": "TextElement", + "value": " - (Private Browsing)", + "span": { + "start": 1335, + "end": 1357 + } + } + ], + "span": { + "start": 1325, + "end": 1357 + } + }, + "default": false, + "span": { + "start": 1317, + "end": 1357 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 1362, + "end": 1367 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "title", + "span": { + "start": 1372, + "end": 1377 + } + }, + "span": { + "start": 1371, + "end": 1377 + } + }, + { + "start": 1371, + "end": 1378 + } + ], + "span": { + "start": 1369, + "end": 1378 + } + }, + { + "type": "TextElement", + "value": " - ", + "span": { + "start": 1379, + "end": 1382 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-full-name", + "span": { + "start": 1385, + "end": 1400 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 1384, + "end": 1401 + } + }, + { + "start": 1384, + "end": 1401 + } + ], + "span": { + "start": 1382, + "end": 1401 + } + }, + { + "type": "TextElement", + "value": " (Private Browsing)", + "span": { + "start": 1402, + "end": 1422 + } + } + ], + "span": { + "start": 1369, + "end": 1422 + } + }, + "default": true, + "span": { + "start": 1360, + "end": 1422 + } + } + ], + "span": { + "start": 1299, + "end": 1422 + } + }, + "span": { + "start": 1297, + "end": 1422 + } + } + ], + "span": { + "start": 1297, + "end": 1425 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1253, + "end": 1425 + } + }, + { + "type": "GroupComment", + "content": [ + "" + ], + "span": { + "start": 1425, + "end": 1427 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-identity-button", + "span": { + "start": 1429, + "end": 1451 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "aria-label", + "span": { + "start": 1459, + "end": 1469 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View site information", + "span": { + "start": 1472, + "end": 1494 + } + } + ], + "span": { + "start": 1472, + "end": 1495 + } + }, + "span": { + "start": 1494, + "end": 1495 + } + } + ], + "comment": null, + "span": { + "start": 1429, + "end": 1495 + } + }, + { + "type": "GroupComment", + "content": [ + "Tooltips for images appearing in the address bar" + ], + "span": { + "start": 1495, + "end": 1546 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-services-notification-anchor", + "span": { + "start": 1548, + "end": 1583 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 1591, + "end": 1602 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open install message panel", + "span": { + "start": 1605, + "end": 1632 + } + } + ], + "span": { + "start": 1605, + "end": 1632 + } + }, + "span": { + "start": 1631, + "end": 1632 + } + } + ], + "comment": null, + "span": { + "start": 1548, + "end": 1632 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-web-notification-anchor", + "span": { + "start": 1632, + "end": 1662 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 1670, + "end": 1681 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Change whether you can receive notifications from the site", + "span": { + "start": 1684, + "end": 1743 + } + } + ], + "span": { + "start": 1684, + "end": 1743 + } + }, + "span": { + "start": 1742, + "end": 1743 + } + } + ], + "comment": null, + "span": { + "start": 1632, + "end": 1743 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-midi-notification-anchor", + "span": { + "start": 1743, + "end": 1774 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 1782, + "end": 1793 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open MIDI panel", + "span": { + "start": 1796, + "end": 1812 + } + } + ], + "span": { + "start": 1796, + "end": 1812 + } + }, + "span": { + "start": 1811, + "end": 1812 + } + } + ], + "comment": null, + "span": { + "start": 1743, + "end": 1812 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-eme-notification-anchor", + "span": { + "start": 1812, + "end": 1842 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 1850, + "end": 1861 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Manage use of DRM software", + "span": { + "start": 1864, + "end": 1891 + } + } + ], + "span": { + "start": 1864, + "end": 1891 + } + }, + "span": { + "start": 1890, + "end": 1891 + } + } + ], + "comment": null, + "span": { + "start": 1812, + "end": 1891 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-web-authn-anchor", + "span": { + "start": 1891, + "end": 1914 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 1922, + "end": 1933 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open Web Authentication panel", + "span": { + "start": 1936, + "end": 1966 + } + } + ], + "span": { + "start": 1936, + "end": 1966 + } + }, + "span": { + "start": 1965, + "end": 1966 + } + } + ], + "comment": null, + "span": { + "start": 1891, + "end": 1966 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-canvas-notification-anchor", + "span": { + "start": 1966, + "end": 1999 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2007, + "end": 2018 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Manage canvas extraction permission", + "span": { + "start": 2021, + "end": 2057 + } + } + ], + "span": { + "start": 2021, + "end": 2057 + } + }, + "span": { + "start": 2056, + "end": 2057 + } + } + ], + "comment": null, + "span": { + "start": 1966, + "end": 2057 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-web-rtc-share-microphone-notification-anchor", + "span": { + "start": 2057, + "end": 2108 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2116, + "end": 2127 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Manage sharing your microphone with the site", + "span": { + "start": 2130, + "end": 2175 + } + } + ], + "span": { + "start": 2130, + "end": 2175 + } + }, + "span": { + "start": 2174, + "end": 2175 + } + } + ], + "comment": null, + "span": { + "start": 2057, + "end": 2175 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-default-notification-anchor", + "span": { + "start": 2175, + "end": 2209 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2217, + "end": 2228 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open message panel", + "span": { + "start": 2231, + "end": 2250 + } + } + ], + "span": { + "start": 2231, + "end": 2250 + } + }, + "span": { + "start": 2249, + "end": 2250 + } + } + ], + "comment": null, + "span": { + "start": 2175, + "end": 2250 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-geolocation-notification-anchor", + "span": { + "start": 2250, + "end": 2288 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2296, + "end": 2307 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open location request panel", + "span": { + "start": 2310, + "end": 2338 + } + } + ], + "span": { + "start": 2310, + "end": 2338 + } + }, + "span": { + "start": 2337, + "end": 2338 + } + } + ], + "comment": null, + "span": { + "start": 2250, + "end": 2338 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-xr-notification-anchor", + "span": { + "start": 2338, + "end": 2367 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2375, + "end": 2386 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open virtual reality permission panel", + "span": { + "start": 2389, + "end": 2427 + } + } + ], + "span": { + "start": 2389, + "end": 2427 + } + }, + "span": { + "start": 2426, + "end": 2427 + } + } + ], + "comment": null, + "span": { + "start": 2338, + "end": 2427 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-storage-access-anchor", + "span": { + "start": 2427, + "end": 2455 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2463, + "end": 2474 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open browsing activity permission panel", + "span": { + "start": 2477, + "end": 2517 + } + } + ], + "span": { + "start": 2477, + "end": 2517 + } + }, + "span": { + "start": 2516, + "end": 2517 + } + } + ], + "comment": null, + "span": { + "start": 2427, + "end": 2517 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-translate-notification-anchor", + "span": { + "start": 2517, + "end": 2553 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2561, + "end": 2572 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Translate this page", + "span": { + "start": 2575, + "end": 2595 + } + } + ], + "span": { + "start": 2575, + "end": 2595 + } + }, + "span": { + "start": 2594, + "end": 2595 + } + } + ], + "comment": null, + "span": { + "start": 2517, + "end": 2595 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-web-rtc-share-screen-notification-anchor", + "span": { + "start": 2595, + "end": 2642 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2650, + "end": 2661 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Manage sharing your windows or screen with the site", + "span": { + "start": 2664, + "end": 2716 + } + } + ], + "span": { + "start": 2664, + "end": 2716 + } + }, + "span": { + "start": 2715, + "end": 2716 + } + } + ], + "comment": null, + "span": { + "start": 2595, + "end": 2716 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-indexed-db-notification-anchor", + "span": { + "start": 2716, + "end": 2753 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2761, + "end": 2772 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open offline storage message panel", + "span": { + "start": 2775, + "end": 2810 + } + } + ], + "span": { + "start": 2775, + "end": 2810 + } + }, + "span": { + "start": 2809, + "end": 2810 + } + } + ], + "comment": null, + "span": { + "start": 2716, + "end": 2810 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-password-notification-anchor", + "span": { + "start": 2810, + "end": 2845 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2853, + "end": 2864 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open save password message panel", + "span": { + "start": 2867, + "end": 2900 + } + } + ], + "span": { + "start": 2867, + "end": 2900 + } + }, + "span": { + "start": 2899, + "end": 2900 + } + } + ], + "comment": null, + "span": { + "start": 2810, + "end": 2900 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-translated-notification-anchor", + "span": { + "start": 2900, + "end": 2937 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2945, + "end": 2956 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Manage page translation", + "span": { + "start": 2959, + "end": 2983 + } + } + ], + "span": { + "start": 2959, + "end": 2983 + } + }, + "span": { + "start": 2982, + "end": 2983 + } + } + ], + "comment": null, + "span": { + "start": 2900, + "end": 2983 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-plugins-notification-anchor", + "span": { + "start": 2983, + "end": 3017 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 3025, + "end": 3036 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Manage plug-in use", + "span": { + "start": 3039, + "end": 3058 + } + } + ], + "span": { + "start": 3039, + "end": 3058 + } + }, + "span": { + "start": 3057, + "end": 3058 + } + } + ], + "comment": null, + "span": { + "start": 2983, + "end": 3058 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-web-rtc-share-devices-notification-anchor", + "span": { + "start": 3058, + "end": 3106 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 3114, + "end": 3125 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Manage sharing your camera and/or microphone with the site", + "span": { + "start": 3128, + "end": 3187 + } + } + ], + "span": { + "start": 3128, + "end": 3187 + } + }, + "span": { + "start": 3186, + "end": 3187 + } + } + ], + "comment": null, + "span": { + "start": 3058, + "end": 3187 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-autoplay-notification-anchor", + "span": { + "start": 3187, + "end": 3222 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 3230, + "end": 3241 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open autoplay panel", + "span": { + "start": 3244, + "end": 3264 + } + } + ], + "span": { + "start": 3244, + "end": 3264 + } + }, + "span": { + "start": 3263, + "end": 3264 + } + } + ], + "comment": null, + "span": { + "start": 3187, + "end": 3264 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-persistent-storage-notification-anchor", + "span": { + "start": 3264, + "end": 3309 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 3317, + "end": 3328 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Store data in Persistent Storage", + "span": { + "start": 3331, + "end": 3364 + } + } + ], + "span": { + "start": 3331, + "end": 3364 + } + }, + "span": { + "start": 3363, + "end": 3364 + } + } + ], + "comment": null, + "span": { + "start": 3264, + "end": 3364 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-addons-notification-anchor", + "span": { + "start": 3364, + "end": 3397 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 3405, + "end": 3416 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open add-on installation message panel", + "span": { + "start": 3419, + "end": 3458 + } + } + ], + "span": { + "start": 3419, + "end": 3458 + } + }, + "span": { + "start": 3457, + "end": 3458 + } + } + ], + "comment": null, + "span": { + "start": 3364, + "end": 3458 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-tip-help-icon", + "span": { + "start": 3458, + "end": 3478 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "title", + "span": { + "start": 3486, + "end": 3491 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Get help", + "span": { + "start": 3494, + "end": 3503 + } + } + ], + "span": { + "start": 3494, + "end": 3503 + } + }, + "span": { + "start": 3502, + "end": 3503 + } + } + ], + "comment": null, + "span": { + "start": 3458, + "end": 3503 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-search-tips-confirm", + "span": { + "start": 3503, + "end": 3529 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Okay, Got It", + "span": { + "start": 3532, + "end": 3545 + } + } + ], + "span": { + "start": 3532, + "end": 3545 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 3503, + "end": 3545 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-tip-icon-description", + "span": { + "start": 3721, + "end": 3748 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "alt", + "span": { + "start": 3756, + "end": 3759 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Tip:", + "span": { + "start": 3762, + "end": 3767 + } + } + ], + "span": { + "start": 3762, + "end": 3768 + } + }, + "span": { + "start": 3767, + "end": 3768 + } + } + ], + "comment": { + "content": [ + "Read out before Urlbar Tip text content so screenreader users know the", + "subsequent text is a tip offered by the browser. It should end in a colon or", + "localized equivalent." + ], + "span": { + "start": 3545, + "end": 3720 + } + }, + "span": { + "start": 3721, + "end": 3768 + } + }, + { + "type": "GroupComment", + "content": [ + "Prompts users to use the Urlbar when they open a new tab or visit the", + "homepage of their default search engine.", + "Variables:", + " $engineName (String): The name of the user's default search engine. e.g. \"Google\" or \"DuckDuckGo\"." + ], + "span": { + "start": 3768, + "end": 4001 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-search-tips-onboard", + "span": { + "start": 4002, + "end": 4028 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Type less, find more: Search ", + "span": { + "start": 4031, + "end": 4060 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "engineName", + "span": { + "start": 4063, + "end": 4073 + } + }, + "span": { + "start": 4062, + "end": 4073 + } + }, + { + "start": 4062, + "end": 4074 + } + ], + "span": { + "start": 4060, + "end": 4074 + } + }, + { + "type": "TextElement", + "value": " right from your address bar.", + "span": { + "start": 4075, + "end": 4105 + } + } + ], + "span": { + "start": 4031, + "end": 4105 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 4002, + "end": 4105 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-search-tips-redirect-2", + "span": { + "start": 4105, + "end": 4134 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Start your search in the address bar to see suggestions from ", + "span": { + "start": 4137, + "end": 4198 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "engineName", + "span": { + "start": 4201, + "end": 4211 + } + }, + "span": { + "start": 4200, + "end": 4211 + } + }, + { + "start": 4200, + "end": 4212 + } + ], + "span": { + "start": 4198, + "end": 4212 + } + }, + { + "type": "TextElement", + "value": " and your browsing history.", + "span": { + "start": 4213, + "end": 4241 + } + } + ], + "span": { + "start": 4137, + "end": 4242 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 4105, + "end": 4242 + } + }, + { + "type": "GroupComment", + "content": [ + "" + ], + "span": { + "start": 4242, + "end": 4244 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-geolocation-blocked", + "span": { + "start": 4246, + "end": 4272 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 4280, + "end": 4291 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked location information for this website.", + "span": { + "start": 4294, + "end": 4350 + } + } + ], + "span": { + "start": 4294, + "end": 4350 + } + }, + "span": { + "start": 4349, + "end": 4350 + } + } + ], + "comment": null, + "span": { + "start": 4246, + "end": 4350 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-xr-blocked", + "span": { + "start": 4350, + "end": 4367 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 4375, + "end": 4386 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked virtual reality device access for this website.", + "span": { + "start": 4389, + "end": 4454 + } + } + ], + "span": { + "start": 4389, + "end": 4454 + } + }, + "span": { + "start": 4453, + "end": 4454 + } + } + ], + "comment": null, + "span": { + "start": 4350, + "end": 4454 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-web-notifications-blocked", + "span": { + "start": 4454, + "end": 4486 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 4494, + "end": 4505 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked notifications for this website.", + "span": { + "start": 4508, + "end": 4557 + } + } + ], + "span": { + "start": 4508, + "end": 4557 + } + }, + "span": { + "start": 4556, + "end": 4557 + } + } + ], + "comment": null, + "span": { + "start": 4454, + "end": 4557 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-camera-blocked", + "span": { + "start": 4557, + "end": 4578 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 4586, + "end": 4597 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked your camera for this website.", + "span": { + "start": 4600, + "end": 4647 + } + } + ], + "span": { + "start": 4600, + "end": 4647 + } + }, + "span": { + "start": 4646, + "end": 4647 + } + } + ], + "comment": null, + "span": { + "start": 4557, + "end": 4647 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-microphone-blocked", + "span": { + "start": 4647, + "end": 4672 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 4680, + "end": 4691 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked your microphone for this website.", + "span": { + "start": 4694, + "end": 4745 + } + } + ], + "span": { + "start": 4694, + "end": 4745 + } + }, + "span": { + "start": 4744, + "end": 4745 + } + } + ], + "comment": null, + "span": { + "start": 4647, + "end": 4745 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-screen-blocked", + "span": { + "start": 4745, + "end": 4766 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 4774, + "end": 4785 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked this website from sharing your screen.", + "span": { + "start": 4788, + "end": 4844 + } + } + ], + "span": { + "start": 4788, + "end": 4844 + } + }, + "span": { + "start": 4843, + "end": 4844 + } + } + ], + "comment": null, + "span": { + "start": 4745, + "end": 4844 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-persistent-storage-blocked", + "span": { + "start": 4844, + "end": 4877 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 4885, + "end": 4896 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked persistent storage for this website.", + "span": { + "start": 4899, + "end": 4953 + } + } + ], + "span": { + "start": 4899, + "end": 4953 + } + }, + "span": { + "start": 4952, + "end": 4953 + } + } + ], + "comment": null, + "span": { + "start": 4844, + "end": 4953 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-popup-blocked", + "span": { + "start": 4953, + "end": 4973 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 4981, + "end": 4992 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked pop-ups for this website.", + "span": { + "start": 4995, + "end": 5038 + } + } + ], + "span": { + "start": 4995, + "end": 5038 + } + }, + "span": { + "start": 5037, + "end": 5038 + } + } + ], + "comment": null, + "span": { + "start": 4953, + "end": 5038 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-autoplay-media-blocked", + "span": { + "start": 5038, + "end": 5067 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 5075, + "end": 5086 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked autoplay media with sound for this website.", + "span": { + "start": 5089, + "end": 5150 + } + } + ], + "span": { + "start": 5089, + "end": 5150 + } + }, + "span": { + "start": 5149, + "end": 5150 + } + } + ], + "comment": null, + "span": { + "start": 5038, + "end": 5150 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-canvas-blocked", + "span": { + "start": 5150, + "end": 5171 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 5179, + "end": 5190 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked canvas data extraction for this website.", + "span": { + "start": 5193, + "end": 5251 + } + } + ], + "span": { + "start": 5193, + "end": 5251 + } + }, + "span": { + "start": 5250, + "end": 5251 + } + } + ], + "comment": null, + "span": { + "start": 5150, + "end": 5251 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-midi-blocked", + "span": { + "start": 5251, + "end": 5270 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 5278, + "end": 5289 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked MIDI access for this website.", + "span": { + "start": 5292, + "end": 5339 + } + } + ], + "span": { + "start": 5292, + "end": 5339 + } + }, + "span": { + "start": 5338, + "end": 5339 + } + } + ], + "comment": null, + "span": { + "start": 5251, + "end": 5339 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-install-blocked", + "span": { + "start": 5339, + "end": 5361 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 5369, + "end": 5380 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have blocked add-on installation for this website.", + "span": { + "start": 5383, + "end": 5438 + } + } + ], + "span": { + "start": 5383, + "end": 5439 + } + }, + "span": { + "start": 5438, + "end": 5439 + } + } + ], + "comment": null, + "span": { + "start": 5339, + "end": 5439 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-star-edit-bookmark", + "span": { + "start": 5527, + "end": 5552 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 5560, + "end": 5571 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Edit this bookmark (", + "span": { + "start": 5574, + "end": 5594 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "shortcut", + "span": { + "start": 5597, + "end": 5605 + } + }, + "span": { + "start": 5596, + "end": 5605 + } + }, + { + "start": 5596, + "end": 5606 + } + ], + "span": { + "start": 5594, + "end": 5606 + } + }, + { + "type": "TextElement", + "value": ")", + "span": { + "start": 5607, + "end": 5609 + } + } + ], + "span": { + "start": 5574, + "end": 5610 + } + }, + "span": { + "start": 5609, + "end": 5610 + } + } + ], + "comment": { + "content": [ + "Variables", + " $shortcut (String) - A keyboard shortcut for the edit bookmark command." + ], + "span": { + "start": 5439, + "end": 5526 + } + }, + "span": { + "start": 5527, + "end": 5610 + } + }, + { + "type": "Message", + "id": { + "name": "urlbar-star-add-bookmark", + "span": { + "start": 5697, + "end": 5721 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 5729, + "end": 5740 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmark this page (", + "span": { + "start": 5743, + "end": 5763 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "shortcut", + "span": { + "start": 5766, + "end": 5774 + } + }, + "span": { + "start": 5765, + "end": 5774 + } + }, + { + "start": 5765, + "end": 5775 + } + ], + "span": { + "start": 5763, + "end": 5775 + } + }, + { + "type": "TextElement", + "value": ")", + "span": { + "start": 5776, + "end": 5778 + } + } + ], + "span": { + "start": 5743, + "end": 5779 + } + }, + "span": { + "start": 5778, + "end": 5779 + } + } + ], + "comment": { + "content": [ + "Variables", + " $shortcut (String) - A keyboard shortcut for the add bookmark command." + ], + "span": { + "start": 5610, + "end": 5696 + } + }, + "span": { + "start": 5697, + "end": 5779 + } + }, + { + "type": "GroupComment", + "content": [ + "Page Action Context Menu" + ], + "span": { + "start": 5779, + "end": 5806 + } + }, + { + "type": "Message", + "id": { + "name": "page-action-add-to-urlbar", + "span": { + "start": 5808, + "end": 5833 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5841, + "end": 5846 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Add to Address Bar", + "span": { + "start": 5849, + "end": 5868 + } + } + ], + "span": { + "start": 5849, + "end": 5868 + } + }, + "span": { + "start": 5867, + "end": 5868 + } + } + ], + "comment": null, + "span": { + "start": 5808, + "end": 5868 + } + }, + { + "type": "Message", + "id": { + "name": "page-action-manage-extension", + "span": { + "start": 5868, + "end": 5896 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5904, + "end": 5909 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Manage Extension…", + "span": { + "start": 5912, + "end": 5932 + } + } + ], + "span": { + "start": 5912, + "end": 5932 + } + }, + "span": { + "start": 5931, + "end": 5932 + } + } + ], + "comment": null, + "span": { + "start": 5868, + "end": 5932 + } + }, + { + "type": "Message", + "id": { + "name": "page-action-remove-from-urlbar", + "span": { + "start": 5932, + "end": 5962 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5970, + "end": 5975 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Remove from Address Bar", + "span": { + "start": 5978, + "end": 6002 + } + } + ], + "span": { + "start": 5978, + "end": 6003 + } + }, + "span": { + "start": 6002, + "end": 6003 + } + } + ], + "comment": null, + "span": { + "start": 5932, + "end": 6003 + } + }, + { + "type": "GroupComment", + "content": [ + "Auto-hide Context Menu" + ], + "span": { + "start": 6003, + "end": 6028 + } + }, + { + "type": "Message", + "id": { + "name": "full-screen-autohide", + "span": { + "start": 6030, + "end": 6050 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6058, + "end": 6063 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Hide Toolbars", + "span": { + "start": 6066, + "end": 6080 + } + } + ], + "span": { + "start": 6066, + "end": 6080 + } + }, + "span": { + "start": 6079, + "end": 6080 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6085, + "end": 6094 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "H", + "span": { + "start": 6097, + "end": 6099 + } + } + ], + "span": { + "start": 6097, + "end": 6099 + } + }, + "span": { + "start": 6098, + "end": 6099 + } + } + ], + "comment": null, + "span": { + "start": 6030, + "end": 6099 + } + }, + { + "type": "Message", + "id": { + "name": "full-screen-exit", + "span": { + "start": 6099, + "end": 6115 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6123, + "end": 6128 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Exit Full Screen Mode", + "span": { + "start": 6131, + "end": 6153 + } + } + ], + "span": { + "start": 6131, + "end": 6153 + } + }, + "span": { + "start": 6152, + "end": 6153 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6158, + "end": 6167 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 6170, + "end": 6172 + } + } + ], + "span": { + "start": 6170, + "end": 6173 + } + }, + "span": { + "start": 6172, + "end": 6173 + } + } + ], + "comment": null, + "span": { + "start": 6099, + "end": 6173 + } + }, + { + "type": "GroupComment", + "content": [ + "Search Engine selection buttons (one-offs)" + ], + "span": { + "start": 6173, + "end": 6218 + } + }, + { + "type": "Message", + "id": { + "name": "search-one-offs-with-title", + "span": { + "start": 6326, + "end": 6352 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "This time, search with:", + "span": { + "start": 6355, + "end": 6379 + } + } + ], + "span": { + "start": 6355, + "end": 6380 + } + }, + "attributes": [], + "comment": { + "content": [ + "This string prompts the user to use the list of one-click search engines in", + "the Urlbar and searchbar." + ], + "span": { + "start": 6220, + "end": 6325 + } + }, + "span": { + "start": 6326, + "end": 6380 + } + }, + { + "type": "Message", + "id": { + "name": "search-one-offs-change-settings-button", + "span": { + "start": 6509, + "end": 6547 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6555, + "end": 6560 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Change Search Settings", + "span": { + "start": 6563, + "end": 6586 + } + } + ], + "span": { + "start": 6563, + "end": 6586 + } + }, + "span": { + "start": 6585, + "end": 6586 + } + } + ], + "comment": { + "content": [ + "This string won't wrap, so if the translated string is longer,", + "consider translating it as if it said only \"Search Settings\"." + ], + "span": { + "start": 6380, + "end": 6508 + } + }, + "span": { + "start": 6509, + "end": 6586 + } + }, + { + "type": "Message", + "id": { + "name": "search-one-offs-change-settings-compact-button", + "span": { + "start": 6586, + "end": 6632 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 6640, + "end": 6651 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Change search settings", + "span": { + "start": 6654, + "end": 6677 + } + } + ], + "span": { + "start": 6654, + "end": 6678 + } + }, + "span": { + "start": 6677, + "end": 6678 + } + } + ], + "comment": null, + "span": { + "start": 6586, + "end": 6678 + } + }, + { + "type": "Message", + "id": { + "name": "search-one-offs-context-open-new-tab", + "span": { + "start": 6678, + "end": 6714 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6722, + "end": 6727 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Search in New Tab", + "span": { + "start": 6730, + "end": 6748 + } + } + ], + "span": { + "start": 6730, + "end": 6748 + } + }, + "span": { + "start": 6747, + "end": 6748 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6753, + "end": 6762 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "T", + "span": { + "start": 6765, + "end": 6767 + } + } + ], + "span": { + "start": 6765, + "end": 6767 + } + }, + "span": { + "start": 6766, + "end": 6767 + } + } + ], + "comment": null, + "span": { + "start": 6678, + "end": 6767 + } + }, + { + "type": "Message", + "id": { + "name": "search-one-offs-context-set-as-default", + "span": { + "start": 6767, + "end": 6805 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6813, + "end": 6818 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Set as Default Search Engine", + "span": { + "start": 6821, + "end": 6850 + } + } + ], + "span": { + "start": 6821, + "end": 6850 + } + }, + "span": { + "start": 6849, + "end": 6850 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6855, + "end": 6864 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 6867, + "end": 6869 + } + } + ], + "span": { + "start": 6867, + "end": 6869 + } + }, + "span": { + "start": 6868, + "end": 6869 + } + } + ], + "comment": null, + "span": { + "start": 6767, + "end": 6869 + } + }, + { + "type": "Message", + "id": { + "name": "search-one-offs-context-set-as-default-private", + "span": { + "start": 6869, + "end": 6915 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6923, + "end": 6928 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Set as Default Search Engine for Private Windows", + "span": { + "start": 6931, + "end": 6980 + } + } + ], + "span": { + "start": 6931, + "end": 6980 + } + }, + "span": { + "start": 6979, + "end": 6980 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6985, + "end": 6994 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "P", + "span": { + "start": 6997, + "end": 6999 + } + } + ], + "span": { + "start": 6997, + "end": 7000 + } + }, + "span": { + "start": 6999, + "end": 7000 + } + } + ], + "comment": null, + "span": { + "start": 6869, + "end": 7000 + } + }, + { + "type": "GroupComment", + "content": [ + "Bookmark Panel" + ], + "span": { + "start": 7000, + "end": 7017 + } + }, + { + "type": "Message", + "id": { + "name": "bookmark-panel-show-editor-checkbox", + "span": { + "start": 7019, + "end": 7054 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7062, + "end": 7067 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Show editor when saving", + "span": { + "start": 7070, + "end": 7094 + } + } + ], + "span": { + "start": 7070, + "end": 7094 + } + }, + "span": { + "start": 7093, + "end": 7094 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7099, + "end": 7108 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "S", + "span": { + "start": 7111, + "end": 7113 + } + } + ], + "span": { + "start": 7111, + "end": 7114 + } + }, + "span": { + "start": 7113, + "end": 7114 + } + } + ], + "comment": null, + "span": { + "start": 7019, + "end": 7114 + } + }, + { + "type": "Message", + "id": { + "name": "bookmark-panel-done-button", + "span": { + "start": 7114, + "end": 7140 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7148, + "end": 7153 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Done", + "span": { + "start": 7156, + "end": 7161 + } + } + ], + "span": { + "start": 7156, + "end": 7162 + } + }, + "span": { + "start": 7161, + "end": 7162 + } + } + ], + "comment": null, + "span": { + "start": 7114, + "end": 7162 + } + }, + { + "type": "Message", + "id": { + "name": "bookmark-panel", + "span": { + "start": 7282, + "end": 7296 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "style", + "span": { + "start": 7304, + "end": 7309 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "min-width: 23em", + "span": { + "start": 7312, + "end": 7328 + } + } + ], + "span": { + "start": 7312, + "end": 7329 + } + }, + "span": { + "start": 7328, + "end": 7329 + } + } + ], + "comment": { + "content": [ + "Width of the bookmark panel.", + "Should be large enough to fully display the Done and", + "Cancel/Remove Bookmark buttons." + ], + "span": { + "start": 7162, + "end": 7281 + } + }, + "span": { + "start": 7282, + "end": 7329 + } + }, + { + "type": "GroupComment", + "content": [ + "Identity Panel" + ], + "span": { + "start": 7329, + "end": 7346 + } + }, + { + "type": "Message", + "id": { + "name": "identity-connection-not-secure", + "span": { + "start": 7348, + "end": 7378 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Connection not secure", + "span": { + "start": 7381, + "end": 7403 + } + } + ], + "span": { + "start": 7381, + "end": 7403 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 7348, + "end": 7403 + } + }, + { + "type": "Message", + "id": { + "name": "identity-connection-secure", + "span": { + "start": 7403, + "end": 7429 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Connection secure", + "span": { + "start": 7432, + "end": 7450 + } + } + ], + "span": { + "start": 7432, + "end": 7450 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 7403, + "end": 7450 + } + }, + { + "type": "Message", + "id": { + "name": "identity-connection-internal", + "span": { + "start": 7450, + "end": 7478 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "This is a secure ", + "span": { + "start": 7481, + "end": 7498 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-short-name", + "span": { + "start": 7501, + "end": 7517 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 7500, + "end": 7518 + } + }, + { + "start": 7500, + "end": 7518 + } + ], + "span": { + "start": 7498, + "end": 7518 + } + }, + { + "type": "TextElement", + "value": " page.", + "span": { + "start": 7519, + "end": 7526 + } + } + ], + "span": { + "start": 7481, + "end": 7526 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 7450, + "end": 7526 + } + }, + { + "type": "Message", + "id": { + "name": "identity-connection-file", + "span": { + "start": 7526, + "end": 7550 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "This page is stored on your computer.", + "span": { + "start": 7553, + "end": 7591 + } + } + ], + "span": { + "start": 7553, + "end": 7591 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 7526, + "end": 7591 + } + }, + { + "type": "Message", + "id": { + "name": "identity-extension-page", + "span": { + "start": 7591, + "end": 7614 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "This page is loaded from an extension.", + "span": { + "start": 7617, + "end": 7656 + } + } + ], + "span": { + "start": 7617, + "end": 7656 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 7591, + "end": 7656 + } + }, + { + "type": "Message", + "id": { + "name": "identity-active-blocked", + "span": { + "start": 7656, + "end": 7679 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-short-name", + "span": { + "start": 7685, + "end": 7701 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 7684, + "end": 7702 + } + }, + { + "start": 7684, + "end": 7702 + } + ], + "span": { + "start": 7682, + "end": 7702 + } + }, + { + "type": "TextElement", + "value": " has blocked parts of this page that are not secure.", + "span": { + "start": 7703, + "end": 7756 + } + } + ], + "span": { + "start": 7682, + "end": 7756 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 7656, + "end": 7756 + } + }, + { + "type": "Message", + "id": { + "name": "identity-custom-root", + "span": { + "start": 7756, + "end": 7776 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Connection verified by a certificate issuer that is not recognized by Mozilla.", + "span": { + "start": 7779, + "end": 7858 + } + } + ], + "span": { + "start": 7779, + "end": 7858 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 7756, + "end": 7858 + } + }, + { + "type": "Message", + "id": { + "name": "identity-passive-loaded", + "span": { + "start": 7858, + "end": 7881 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Parts of this page are not secure (such as images).", + "span": { + "start": 7884, + "end": 7936 + } + } + ], + "span": { + "start": 7884, + "end": 7936 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 7858, + "end": 7936 + } + }, + { + "type": "Message", + "id": { + "name": "identity-active-loaded", + "span": { + "start": 7936, + "end": 7958 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have disabled protection on this page.", + "span": { + "start": 7961, + "end": 8004 + } + } + ], + "span": { + "start": 7961, + "end": 8004 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 7936, + "end": 8004 + } + }, + { + "type": "Message", + "id": { + "name": "identity-weak-encryption", + "span": { + "start": 8004, + "end": 8028 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "This page uses weak encryption.", + "span": { + "start": 8031, + "end": 8063 + } + } + ], + "span": { + "start": 8031, + "end": 8063 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 8004, + "end": 8063 + } + }, + { + "type": "Message", + "id": { + "name": "identity-insecure-login-forms", + "span": { + "start": 8063, + "end": 8092 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Logins entered on this page could be compromised.", + "span": { + "start": 8095, + "end": 8145 + } + } + ], + "span": { + "start": 8095, + "end": 8145 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 8063, + "end": 8145 + } + }, + { + "type": "Message", + "id": { + "name": "identity-permissions", + "span": { + "start": 8145, + "end": 8165 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "value", + "span": { + "start": 8173, + "end": 8178 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Permissions", + "span": { + "start": 8181, + "end": 8193 + } + } + ], + "span": { + "start": 8181, + "end": 8193 + } + }, + "span": { + "start": 8192, + "end": 8193 + } + } + ], + "comment": null, + "span": { + "start": 8145, + "end": 8193 + } + }, + { + "type": "Message", + "id": { + "name": "identity-permissions-reload-hint", + "span": { + "start": 8193, + "end": 8225 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You may need to reload the page for changes to apply.", + "span": { + "start": 8228, + "end": 8282 + } + } + ], + "span": { + "start": 8228, + "end": 8282 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 8193, + "end": 8282 + } + }, + { + "type": "Message", + "id": { + "name": "identity-permissions-empty", + "span": { + "start": 8282, + "end": 8308 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You have not granted this site any special permissions.", + "span": { + "start": 8311, + "end": 8367 + } + } + ], + "span": { + "start": 8311, + "end": 8367 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 8282, + "end": 8367 + } + }, + { + "type": "Message", + "id": { + "name": "identity-clear-site-data", + "span": { + "start": 8367, + "end": 8391 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8399, + "end": 8404 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Clear Cookies and Site Data…", + "span": { + "start": 8407, + "end": 8438 + } + } + ], + "span": { + "start": 8407, + "end": 8438 + } + }, + "span": { + "start": 8437, + "end": 8438 + } + } + ], + "comment": null, + "span": { + "start": 8367, + "end": 8438 + } + }, + { + "type": "Message", + "id": { + "name": "identity-connection-not-secure-security-view", + "span": { + "start": 8438, + "end": 8482 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You are not securely connected to this site.", + "span": { + "start": 8485, + "end": 8530 + } + } + ], + "span": { + "start": 8485, + "end": 8530 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 8438, + "end": 8530 + } + }, + { + "type": "Message", + "id": { + "name": "identity-connection-verified", + "span": { + "start": 8530, + "end": 8558 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "You are securely connected to this site.", + "span": { + "start": 8561, + "end": 8602 + } + } + ], + "span": { + "start": 8561, + "end": 8602 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 8530, + "end": 8602 + } + }, + { + "type": "Message", + "id": { + "name": "identity-ev-owner-label", + "span": { + "start": 8602, + "end": 8625 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Certificate issued to:", + "span": { + "start": 8628, + "end": 8651 + } + } + ], + "span": { + "start": 8628, + "end": 8651 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 8602, + "end": 8651 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-custom-root", + "span": { + "start": 8651, + "end": 8683 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Mozilla does not recognize this certificate issuer. It may have been added from your operating system or by an administrator. ", + "span": { + "start": 8686, + "end": 8860 + } + } + ], + "span": { + "start": 8686, + "end": 8860 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 8651, + "end": 8860 + } + }, + { + "type": "Message", + "id": { + "name": "identity-remove-cert-exception", + "span": { + "start": 8860, + "end": 8890 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8898, + "end": 8903 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Remove Exception", + "span": { + "start": 8906, + "end": 8923 + } + } + ], + "span": { + "start": 8906, + "end": 8923 + } + }, + "span": { + "start": 8922, + "end": 8923 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8928, + "end": 8937 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 8940, + "end": 8942 + } + } + ], + "span": { + "start": 8940, + "end": 8942 + } + }, + "span": { + "start": 8941, + "end": 8942 + } + } + ], + "comment": null, + "span": { + "start": 8860, + "end": 8942 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-insecure", + "span": { + "start": 8942, + "end": 8971 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Your connection to this site is not private. Information you submit could be viewed by others (like passwords, messages, credit cards, etc.).", + "span": { + "start": 8974, + "end": 9116 + } + } + ], + "span": { + "start": 8974, + "end": 9116 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 8942, + "end": 9116 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-insecure-login-forms", + "span": { + "start": 9116, + "end": 9157 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "The login information you enter on this page is not secure and could be compromised.", + "span": { + "start": 9160, + "end": 9245 + } + } + ], + "span": { + "start": 9160, + "end": 9245 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 9116, + "end": 9245 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-weak-cipher-intro", + "span": { + "start": 9245, + "end": 9283 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Your connection to this website uses weak encryption and is not private.", + "span": { + "start": 9286, + "end": 9359 + } + } + ], + "span": { + "start": 9286, + "end": 9359 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 9245, + "end": 9359 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-weak-cipher-risk", + "span": { + "start": 9359, + "end": 9396 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Other people can view your information or modify the website’s behavior.", + "span": { + "start": 9399, + "end": 9474 + } + } + ], + "span": { + "start": 9399, + "end": 9474 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 9359, + "end": 9474 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-active-blocked", + "span": { + "start": 9474, + "end": 9509 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-short-name", + "span": { + "start": 9515, + "end": 9531 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 9514, + "end": 9532 + } + }, + { + "start": 9514, + "end": 9532 + } + ], + "span": { + "start": 9512, + "end": 9532 + } + }, + { + "type": "TextElement", + "value": " has blocked parts of this page that are not secure. ", + "span": { + "start": 9533, + "end": 9634 + } + } + ], + "span": { + "start": 9512, + "end": 9634 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 9474, + "end": 9634 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-passive-loaded", + "span": { + "start": 9634, + "end": 9669 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Your connection is not private and information you share with the site could be viewed by others.", + "span": { + "start": 9672, + "end": 9770 + } + } + ], + "span": { + "start": 9672, + "end": 9770 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 9634, + "end": 9770 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-passive-loaded-insecure", + "span": { + "start": 9770, + "end": 9814 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "This website contains content that is not secure (such as images). ", + "span": { + "start": 9817, + "end": 9932 + } + } + ], + "span": { + "start": 9817, + "end": 9932 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 9770, + "end": 9932 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-passive-loaded-mixed", + "span": { + "start": 9932, + "end": 9973 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Although ", + "span": { + "start": 9976, + "end": 9985 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-short-name", + "span": { + "start": 9988, + "end": 10004 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 9987, + "end": 10005 + } + }, + { + "start": 9987, + "end": 10005 + } + ], + "span": { + "start": 9985, + "end": 10005 + } + }, + { + "type": "TextElement", + "value": " has blocked some content, there is still content on the page that is not secure (such as images). ", + "span": { + "start": 10006, + "end": 10153 + } + } + ], + "span": { + "start": 9976, + "end": 10153 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 9932, + "end": 10153 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-active-loaded", + "span": { + "start": 10153, + "end": 10187 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "This website contains content that is not secure (such as scripts) and your connection to it is not private.", + "span": { + "start": 10190, + "end": 10299 + } + } + ], + "span": { + "start": 10190, + "end": 10299 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 10153, + "end": 10299 + } + }, + { + "type": "Message", + "id": { + "name": "identity-description-active-loaded-insecure", + "span": { + "start": 10299, + "end": 10342 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Information you share with this site could be viewed by others (like passwords, messages, credit cards, etc.).", + "span": { + "start": 10345, + "end": 10456 + } + } + ], + "span": { + "start": 10345, + "end": 10456 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 10299, + "end": 10456 + } + }, + { + "type": "Message", + "id": { + "name": "identity-learn-more", + "span": { + "start": 10456, + "end": 10475 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "value", + "span": { + "start": 10483, + "end": 10488 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Learn More", + "span": { + "start": 10491, + "end": 10502 + } + } + ], + "span": { + "start": 10491, + "end": 10502 + } + }, + "span": { + "start": 10501, + "end": 10502 + } + } + ], + "comment": null, + "span": { + "start": 10456, + "end": 10502 + } + }, + { + "type": "Message", + "id": { + "name": "identity-disable-mixed-content-blocking", + "span": { + "start": 10502, + "end": 10541 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 10549, + "end": 10554 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Disable protection for now", + "span": { + "start": 10557, + "end": 10584 + } + } + ], + "span": { + "start": 10557, + "end": 10584 + } + }, + "span": { + "start": 10583, + "end": 10584 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 10589, + "end": 10598 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 10601, + "end": 10603 + } + } + ], + "span": { + "start": 10601, + "end": 10603 + } + }, + "span": { + "start": 10602, + "end": 10603 + } + } + ], + "comment": null, + "span": { + "start": 10502, + "end": 10603 + } + }, + { + "type": "Message", + "id": { + "name": "identity-enable-mixed-content-blocking", + "span": { + "start": 10603, + "end": 10641 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 10649, + "end": 10654 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Enable protection", + "span": { + "start": 10657, + "end": 10675 + } + } + ], + "span": { + "start": 10657, + "end": 10675 + } + }, + "span": { + "start": 10674, + "end": 10675 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 10680, + "end": 10689 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "E", + "span": { + "start": 10692, + "end": 10694 + } + } + ], + "span": { + "start": 10692, + "end": 10694 + } + }, + "span": { + "start": 10693, + "end": 10694 + } + } + ], + "comment": null, + "span": { + "start": 10603, + "end": 10694 + } + }, + { + "type": "Message", + "id": { + "name": "identity-more-info-link-text", + "span": { + "start": 10694, + "end": 10722 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 10730, + "end": 10735 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "More Information", + "span": { + "start": 10738, + "end": 10755 + } + } + ], + "span": { + "start": 10738, + "end": 10755 + } + }, + "span": { + "start": 10754, + "end": 10755 + } + } + ], + "comment": null, + "span": { + "start": 10694, + "end": 10755 + } + } + ], + "span": { + "start": 0, + "end": 10755 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/browserContext.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/browserContext.spans.json new file mode 100644 index 00000000..aaf39af8 --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/browserContext.spans.json @@ -0,0 +1,7109 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "Message", + "id": { + "name": "navbar-tooltip-instruction", + "span": { + "start": 200, + "end": 226 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "value", + "span": { + "start": 234, + "end": 239 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "PLATFORM", + "span": { + "start": 244, + "end": 252 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 252, + "end": 254 + } + }, + "span": { + "start": 244, + "end": 254 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "macos", + "span": { + "start": 267, + "end": 272 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Pull down to show history", + "span": { + "start": 274, + "end": 300 + } + } + ], + "span": { + "start": 274, + "end": 300 + } + }, + "default": false, + "span": { + "start": 266, + "end": 300 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 309, + "end": 314 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Right-click or pull down to show history", + "span": { + "start": 316, + "end": 357 + } + } + ], + "span": { + "start": 316, + "end": 357 + } + }, + "default": true, + "span": { + "start": 307, + "end": 357 + } + } + ], + "span": { + "start": 244, + "end": 361 + } + }, + "span": { + "start": 242, + "end": 361 + } + } + ], + "span": { + "start": 242, + "end": 364 + } + }, + "span": { + "start": 363, + "end": 364 + } + } + ], + "comment": null, + "span": { + "start": 200, + "end": 364 + } + }, + { + "type": "GroupComment", + "content": [ + "Back" + ], + "span": { + "start": 364, + "end": 371 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-back", + "span": { + "start": 373, + "end": 395 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 403, + "end": 414 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Go back one page", + "span": { + "start": 417, + "end": 434 + } + } + ], + "span": { + "start": 417, + "end": 434 + } + }, + "span": { + "start": 433, + "end": 434 + } + }, + { + "id": { + "name": "aria-label", + "span": { + "start": 439, + "end": 449 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Back", + "span": { + "start": 452, + "end": 457 + } + } + ], + "span": { + "start": 452, + "end": 457 + } + }, + "span": { + "start": 456, + "end": 457 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 462, + "end": 471 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "B", + "span": { + "start": 474, + "end": 476 + } + } + ], + "span": { + "start": 474, + "end": 477 + } + }, + "span": { + "start": 476, + "end": 477 + } + } + ], + "comment": null, + "span": { + "start": 373, + "end": 477 + } + }, + { + "type": "Message", + "id": { + "name": "navbar-tooltip-back", + "span": { + "start": 477, + "end": 496 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "value", + "span": { + "start": 505, + "end": 510 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "main-context-menu-back", + "span": { + "start": 515, + "end": 537 + } + }, + "attribute": { + "name": "tooltiptext", + "span": { + "start": 538, + "end": 549 + } + }, + "span": { + "start": 515, + "end": 549 + } + }, + { + "start": 515, + "end": 550 + } + ], + "span": { + "start": 513, + "end": 550 + } + } + ], + "span": { + "start": 513, + "end": 553 + } + }, + "span": { + "start": 552, + "end": 553 + } + } + ], + "comment": null, + "span": { + "start": 477, + "end": 553 + } + }, + { + "type": "Message", + "id": { + "name": "toolbar-button-back", + "span": { + "start": 553, + "end": 572 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 580, + "end": 585 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "main-context-menu-back", + "span": { + "start": 590, + "end": 612 + } + }, + "attribute": { + "name": "aria-label", + "span": { + "start": 613, + "end": 623 + } + }, + "span": { + "start": 590, + "end": 623 + } + }, + { + "start": 590, + "end": 624 + } + ], + "span": { + "start": 588, + "end": 624 + } + } + ], + "span": { + "start": 588, + "end": 627 + } + }, + "span": { + "start": 626, + "end": 627 + } + } + ], + "comment": null, + "span": { + "start": 553, + "end": 627 + } + }, + { + "type": "GroupComment", + "content": [ + "Forward" + ], + "span": { + "start": 627, + "end": 637 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-forward", + "span": { + "start": 639, + "end": 664 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "tooltiptext", + "span": { + "start": 672, + "end": 683 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Go forward one page", + "span": { + "start": 686, + "end": 706 + } + } + ], + "span": { + "start": 686, + "end": 706 + } + }, + "span": { + "start": 705, + "end": 706 + } + }, + { + "id": { + "name": "aria-label", + "span": { + "start": 711, + "end": 721 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Forward", + "span": { + "start": 724, + "end": 732 + } + } + ], + "span": { + "start": 724, + "end": 732 + } + }, + "span": { + "start": 731, + "end": 732 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 737, + "end": 746 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 749, + "end": 751 + } + } + ], + "span": { + "start": 749, + "end": 752 + } + }, + "span": { + "start": 751, + "end": 752 + } + } + ], + "comment": null, + "span": { + "start": 639, + "end": 752 + } + }, + { + "type": "Message", + "id": { + "name": "navbar-tooltip-forward", + "span": { + "start": 752, + "end": 774 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "value", + "span": { + "start": 782, + "end": 787 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "main-context-menu-forward", + "span": { + "start": 792, + "end": 817 + } + }, + "attribute": { + "name": "tooltiptext", + "span": { + "start": 818, + "end": 829 + } + }, + "span": { + "start": 792, + "end": 829 + } + }, + { + "start": 792, + "end": 830 + } + ], + "span": { + "start": 790, + "end": 830 + } + } + ], + "span": { + "start": 790, + "end": 834 + } + }, + "span": { + "start": 833, + "end": 834 + } + } + ], + "comment": null, + "span": { + "start": 752, + "end": 834 + } + }, + { + "type": "Message", + "id": { + "name": "toolbar-button-forward", + "span": { + "start": 834, + "end": 856 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 864, + "end": 869 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "main-context-menu-forward", + "span": { + "start": 874, + "end": 899 + } + }, + "attribute": { + "name": "aria-label", + "span": { + "start": 900, + "end": 910 + } + }, + "span": { + "start": 874, + "end": 910 + } + }, + { + "start": 874, + "end": 911 + } + ], + "span": { + "start": 872, + "end": 911 + } + } + ], + "span": { + "start": 872, + "end": 914 + } + }, + "span": { + "start": 913, + "end": 914 + } + } + ], + "comment": null, + "span": { + "start": 834, + "end": 914 + } + }, + { + "type": "GroupComment", + "content": [ + "Reload" + ], + "span": { + "start": 914, + "end": 923 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-reload", + "span": { + "start": 925, + "end": 949 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "aria-label", + "span": { + "start": 957, + "end": 967 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Reload", + "span": { + "start": 970, + "end": 977 + } + } + ], + "span": { + "start": 970, + "end": 977 + } + }, + "span": { + "start": 976, + "end": 977 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 982, + "end": 991 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 994, + "end": 996 + } + } + ], + "span": { + "start": 994, + "end": 997 + } + }, + "span": { + "start": 996, + "end": 997 + } + } + ], + "comment": null, + "span": { + "start": 925, + "end": 997 + } + }, + { + "type": "Message", + "id": { + "name": "toolbar-button-reload", + "span": { + "start": 997, + "end": 1018 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1026, + "end": 1031 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "main-context-menu-reload", + "span": { + "start": 1036, + "end": 1060 + } + }, + "attribute": { + "name": "aria-label", + "span": { + "start": 1061, + "end": 1071 + } + }, + "span": { + "start": 1036, + "end": 1071 + } + }, + { + "start": 1036, + "end": 1072 + } + ], + "span": { + "start": 1034, + "end": 1072 + } + } + ], + "span": { + "start": 1034, + "end": 1075 + } + }, + "span": { + "start": 1074, + "end": 1075 + } + } + ], + "comment": null, + "span": { + "start": 997, + "end": 1075 + } + }, + { + "type": "GroupComment", + "content": [ + "Stop" + ], + "span": { + "start": 1075, + "end": 1082 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-stop", + "span": { + "start": 1084, + "end": 1106 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "aria-label", + "span": { + "start": 1114, + "end": 1124 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Stop", + "span": { + "start": 1127, + "end": 1132 + } + } + ], + "span": { + "start": 1127, + "end": 1132 + } + }, + "span": { + "start": 1131, + "end": 1132 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1137, + "end": 1146 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "S", + "span": { + "start": 1149, + "end": 1151 + } + } + ], + "span": { + "start": 1149, + "end": 1152 + } + }, + "span": { + "start": 1151, + "end": 1152 + } + } + ], + "comment": null, + "span": { + "start": 1084, + "end": 1152 + } + }, + { + "type": "Message", + "id": { + "name": "toolbar-button-stop", + "span": { + "start": 1152, + "end": 1171 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1179, + "end": 1184 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "main-context-menu-stop", + "span": { + "start": 1189, + "end": 1211 + } + }, + "attribute": { + "name": "aria-label", + "span": { + "start": 1212, + "end": 1222 + } + }, + "span": { + "start": 1189, + "end": 1222 + } + }, + { + "start": 1189, + "end": 1223 + } + ], + "span": { + "start": 1187, + "end": 1223 + } + } + ], + "span": { + "start": 1187, + "end": 1226 + } + }, + "span": { + "start": 1225, + "end": 1226 + } + } + ], + "comment": null, + "span": { + "start": 1152, + "end": 1226 + } + }, + { + "type": "GroupComment", + "content": [ + "Stop-Reload Button" + ], + "span": { + "start": 1226, + "end": 1247 + } + }, + { + "type": "Message", + "id": { + "name": "toolbar-button-stop-reload", + "span": { + "start": 1249, + "end": 1275 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "title", + "span": { + "start": 1283, + "end": 1288 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "main-context-menu-reload", + "span": { + "start": 1293, + "end": 1317 + } + }, + "attribute": { + "name": "aria-label", + "span": { + "start": 1318, + "end": 1328 + } + }, + "span": { + "start": 1293, + "end": 1328 + } + }, + { + "start": 1293, + "end": 1329 + } + ], + "span": { + "start": 1291, + "end": 1329 + } + } + ], + "span": { + "start": 1291, + "end": 1332 + } + }, + "span": { + "start": 1331, + "end": 1332 + } + } + ], + "comment": null, + "span": { + "start": 1249, + "end": 1332 + } + }, + { + "type": "GroupComment", + "content": [ + "Save Page" + ], + "span": { + "start": 1332, + "end": 1344 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-page-save", + "span": { + "start": 1346, + "end": 1373 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1381, + "end": 1386 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Save Page As…", + "span": { + "start": 1389, + "end": 1405 + } + } + ], + "span": { + "start": 1389, + "end": 1405 + } + }, + "span": { + "start": 1404, + "end": 1405 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1410, + "end": 1419 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "P", + "span": { + "start": 1422, + "end": 1424 + } + } + ], + "span": { + "start": 1422, + "end": 1425 + } + }, + "span": { + "start": 1424, + "end": 1425 + } + } + ], + "comment": null, + "span": { + "start": 1346, + "end": 1425 + } + }, + { + "type": "Message", + "id": { + "name": "toolbar-button-page-save", + "span": { + "start": 1425, + "end": 1449 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1457, + "end": 1462 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "MessageReference", + "id": { + "name": "main-context-menu-page-save", + "span": { + "start": 1467, + "end": 1494 + } + }, + "attribute": { + "name": "label", + "span": { + "start": 1495, + "end": 1500 + } + }, + "span": { + "start": 1467, + "end": 1500 + } + }, + { + "start": 1467, + "end": 1501 + } + ], + "span": { + "start": 1465, + "end": 1501 + } + } + ], + "span": { + "start": 1465, + "end": 1504 + } + }, + "span": { + "start": 1503, + "end": 1504 + } + } + ], + "comment": null, + "span": { + "start": 1425, + "end": 1504 + } + }, + { + "type": "GroupComment", + "content": [ + "Simple menu items" + ], + "span": { + "start": 1504, + "end": 1524 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-bookmark-add", + "span": { + "start": 1526, + "end": 1556 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "aria-label", + "span": { + "start": 1564, + "end": 1574 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmark This Page", + "span": { + "start": 1577, + "end": 1596 + } + } + ], + "span": { + "start": 1577, + "end": 1596 + } + }, + "span": { + "start": 1595, + "end": 1596 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1601, + "end": 1610 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "m", + "span": { + "start": 1613, + "end": 1615 + } + } + ], + "span": { + "start": 1613, + "end": 1615 + } + }, + "span": { + "start": 1614, + "end": 1615 + } + }, + { + "id": { + "name": "tooltiptext", + "span": { + "start": 1620, + "end": 1631 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmark this page", + "span": { + "start": 1634, + "end": 1653 + } + } + ], + "span": { + "start": 1634, + "end": 1654 + } + }, + "span": { + "start": 1653, + "end": 1654 + } + } + ], + "comment": null, + "span": { + "start": 1526, + "end": 1654 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-bookmark-add-with-shortcut", + "span": { + "start": 1741, + "end": 1785 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "aria-label", + "span": { + "start": 1793, + "end": 1803 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmark This Page", + "span": { + "start": 1806, + "end": 1825 + } + } + ], + "span": { + "start": 1806, + "end": 1825 + } + }, + "span": { + "start": 1824, + "end": 1825 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1830, + "end": 1839 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "m", + "span": { + "start": 1842, + "end": 1844 + } + } + ], + "span": { + "start": 1842, + "end": 1844 + } + }, + "span": { + "start": 1843, + "end": 1844 + } + }, + { + "id": { + "name": "tooltiptext", + "span": { + "start": 1849, + "end": 1860 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmark this page (", + "span": { + "start": 1863, + "end": 1883 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "shortcut", + "span": { + "start": 1886, + "end": 1894 + } + }, + "span": { + "start": 1885, + "end": 1894 + } + }, + { + "start": 1885, + "end": 1895 + } + ], + "span": { + "start": 1883, + "end": 1895 + } + }, + { + "type": "TextElement", + "value": ")", + "span": { + "start": 1896, + "end": 1898 + } + } + ], + "span": { + "start": 1863, + "end": 1899 + } + }, + "span": { + "start": 1898, + "end": 1899 + } + } + ], + "comment": { + "content": [ + "Variables", + " $shortcut (String) - A keyboard shortcut for the add bookmark command." + ], + "span": { + "start": 1654, + "end": 1740 + } + }, + "span": { + "start": 1741, + "end": 1899 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-bookmark-change", + "span": { + "start": 1899, + "end": 1932 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "aria-label", + "span": { + "start": 1940, + "end": 1950 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Edit This Bookmark", + "span": { + "start": 1953, + "end": 1972 + } + } + ], + "span": { + "start": 1953, + "end": 1972 + } + }, + "span": { + "start": 1971, + "end": 1972 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1977, + "end": 1986 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "m", + "span": { + "start": 1989, + "end": 1991 + } + } + ], + "span": { + "start": 1989, + "end": 1991 + } + }, + "span": { + "start": 1990, + "end": 1991 + } + }, + { + "id": { + "name": "tooltiptext", + "span": { + "start": 1996, + "end": 2007 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Edit this bookmark", + "span": { + "start": 2010, + "end": 2029 + } + } + ], + "span": { + "start": 2010, + "end": 2030 + } + }, + "span": { + "start": 2029, + "end": 2030 + } + } + ], + "comment": null, + "span": { + "start": 1899, + "end": 2030 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-bookmark-change-with-shortcut", + "span": { + "start": 2118, + "end": 2165 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "aria-label", + "span": { + "start": 2173, + "end": 2183 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Edit This Bookmark", + "span": { + "start": 2186, + "end": 2205 + } + } + ], + "span": { + "start": 2186, + "end": 2205 + } + }, + "span": { + "start": 2204, + "end": 2205 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2210, + "end": 2219 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "m", + "span": { + "start": 2222, + "end": 2224 + } + } + ], + "span": { + "start": 2222, + "end": 2224 + } + }, + "span": { + "start": 2223, + "end": 2224 + } + }, + { + "id": { + "name": "tooltiptext", + "span": { + "start": 2229, + "end": 2240 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Edit this bookmark (", + "span": { + "start": 2243, + "end": 2263 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "VariableReference", + "id": { + "name": "shortcut", + "span": { + "start": 2266, + "end": 2274 + } + }, + "span": { + "start": 2265, + "end": 2274 + } + }, + { + "start": 2265, + "end": 2275 + } + ], + "span": { + "start": 2263, + "end": 2275 + } + }, + { + "type": "TextElement", + "value": ")", + "span": { + "start": 2276, + "end": 2278 + } + } + ], + "span": { + "start": 2243, + "end": 2279 + } + }, + "span": { + "start": 2278, + "end": 2279 + } + } + ], + "comment": { + "content": [ + "Variables", + " $shortcut (String) - A keyboard shortcut for the edit bookmark command." + ], + "span": { + "start": 2030, + "end": 2117 + } + }, + "span": { + "start": 2118, + "end": 2279 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-open-link", + "span": { + "start": 2279, + "end": 2306 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2314, + "end": 2319 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open Link", + "span": { + "start": 2322, + "end": 2332 + } + } + ], + "span": { + "start": 2322, + "end": 2332 + } + }, + "span": { + "start": 2331, + "end": 2332 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2337, + "end": 2346 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "O", + "span": { + "start": 2349, + "end": 2351 + } + } + ], + "span": { + "start": 2349, + "end": 2352 + } + }, + "span": { + "start": 2351, + "end": 2352 + } + } + ], + "comment": null, + "span": { + "start": 2279, + "end": 2352 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-open-link-new-tab", + "span": { + "start": 2352, + "end": 2387 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2395, + "end": 2400 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open Link in New Tab", + "span": { + "start": 2403, + "end": 2424 + } + } + ], + "span": { + "start": 2403, + "end": 2424 + } + }, + "span": { + "start": 2423, + "end": 2424 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2429, + "end": 2438 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "T", + "span": { + "start": 2441, + "end": 2443 + } + } + ], + "span": { + "start": 2441, + "end": 2444 + } + }, + "span": { + "start": 2443, + "end": 2444 + } + } + ], + "comment": null, + "span": { + "start": 2352, + "end": 2444 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-open-link-container-tab", + "span": { + "start": 2444, + "end": 2485 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2493, + "end": 2498 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open Link in New Container Tab", + "span": { + "start": 2501, + "end": 2532 + } + } + ], + "span": { + "start": 2501, + "end": 2532 + } + }, + "span": { + "start": 2531, + "end": 2532 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2537, + "end": 2546 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "b", + "span": { + "start": 2549, + "end": 2551 + } + } + ], + "span": { + "start": 2549, + "end": 2552 + } + }, + "span": { + "start": 2551, + "end": 2552 + } + } + ], + "comment": null, + "span": { + "start": 2444, + "end": 2552 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-open-link-new-window", + "span": { + "start": 2552, + "end": 2590 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2598, + "end": 2603 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open Link in New Window", + "span": { + "start": 2606, + "end": 2630 + } + } + ], + "span": { + "start": 2606, + "end": 2630 + } + }, + "span": { + "start": 2629, + "end": 2630 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2635, + "end": 2644 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "W", + "span": { + "start": 2647, + "end": 2649 + } + } + ], + "span": { + "start": 2647, + "end": 2650 + } + }, + "span": { + "start": 2649, + "end": 2650 + } + } + ], + "comment": null, + "span": { + "start": 2552, + "end": 2650 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-open-link-new-private-window", + "span": { + "start": 2650, + "end": 2696 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2704, + "end": 2709 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open Link in New Private Window", + "span": { + "start": 2712, + "end": 2744 + } + } + ], + "span": { + "start": 2712, + "end": 2744 + } + }, + "span": { + "start": 2743, + "end": 2744 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2749, + "end": 2758 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "P", + "span": { + "start": 2761, + "end": 2763 + } + } + ], + "span": { + "start": 2761, + "end": 2764 + } + }, + "span": { + "start": 2763, + "end": 2764 + } + } + ], + "comment": null, + "span": { + "start": 2650, + "end": 2764 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-bookmark-this-link", + "span": { + "start": 2764, + "end": 2800 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2808, + "end": 2813 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmark This Link", + "span": { + "start": 2816, + "end": 2835 + } + } + ], + "span": { + "start": 2816, + "end": 2835 + } + }, + "span": { + "start": 2834, + "end": 2835 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2840, + "end": 2849 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "L", + "span": { + "start": 2852, + "end": 2854 + } + } + ], + "span": { + "start": 2852, + "end": 2855 + } + }, + "span": { + "start": 2854, + "end": 2855 + } + } + ], + "comment": null, + "span": { + "start": 2764, + "end": 2855 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-save-link", + "span": { + "start": 2855, + "end": 2882 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2890, + "end": 2895 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Save Link As…", + "span": { + "start": 2898, + "end": 2914 + } + } + ], + "span": { + "start": 2898, + "end": 2914 + } + }, + "span": { + "start": 2913, + "end": 2914 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2919, + "end": 2928 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "k", + "span": { + "start": 2931, + "end": 2933 + } + } + ], + "span": { + "start": 2931, + "end": 2934 + } + }, + "span": { + "start": 2933, + "end": 2934 + } + } + ], + "comment": null, + "span": { + "start": 2855, + "end": 2934 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-save-link-to-pocket", + "span": { + "start": 2934, + "end": 2971 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2979, + "end": 2984 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Save Link to ", + "span": { + "start": 2987, + "end": 3000 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "pocket-brand-name", + "span": { + "start": 3003, + "end": 3020 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 3002, + "end": 3021 + } + }, + { + "start": 3002, + "end": 3021 + } + ], + "span": { + "start": 3000, + "end": 3021 + } + } + ], + "span": { + "start": 2987, + "end": 3023 + } + }, + "span": { + "start": 3022, + "end": 3023 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3028, + "end": 3037 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "o", + "span": { + "start": 3040, + "end": 3042 + } + } + ], + "span": { + "start": 3040, + "end": 3043 + } + }, + "span": { + "start": 3042, + "end": 3043 + } + } + ], + "comment": null, + "span": { + "start": 2934, + "end": 3043 + } + }, + { + "type": "GroupComment", + "content": [ + "The access keys for \"Copy Link Location\" and \"Copy Email Address\"", + "should be the same if possible; the two context menu items", + "are mutually exclusive." + ], + "span": { + "start": 3043, + "end": 3200 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-copy-email", + "span": { + "start": 3202, + "end": 3230 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3238, + "end": 3243 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Copy Email Address", + "span": { + "start": 3246, + "end": 3265 + } + } + ], + "span": { + "start": 3246, + "end": 3265 + } + }, + "span": { + "start": 3264, + "end": 3265 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3270, + "end": 3279 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A", + "span": { + "start": 3282, + "end": 3284 + } + } + ], + "span": { + "start": 3282, + "end": 3285 + } + }, + "span": { + "start": 3284, + "end": 3285 + } + } + ], + "comment": null, + "span": { + "start": 3202, + "end": 3285 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-copy-link", + "span": { + "start": 3285, + "end": 3312 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3320, + "end": 3325 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Copy Link Location", + "span": { + "start": 3328, + "end": 3347 + } + } + ], + "span": { + "start": 3328, + "end": 3347 + } + }, + "span": { + "start": 3346, + "end": 3347 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3352, + "end": 3361 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "a", + "span": { + "start": 3364, + "end": 3366 + } + } + ], + "span": { + "start": 3364, + "end": 3367 + } + }, + "span": { + "start": 3366, + "end": 3367 + } + } + ], + "comment": null, + "span": { + "start": 3285, + "end": 3367 + } + }, + { + "type": "GroupComment", + "content": [ + "Media (video/audio) controls", + "", + "The accesskey for \"Play\" and \"Pause\" are the", + "same because the two context-menu items are", + "mutually exclusive." + ], + "span": { + "start": 3367, + "end": 3519 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-play", + "span": { + "start": 3521, + "end": 3549 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3557, + "end": 3562 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Play", + "span": { + "start": 3565, + "end": 3570 + } + } + ], + "span": { + "start": 3565, + "end": 3570 + } + }, + "span": { + "start": 3569, + "end": 3570 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3575, + "end": 3584 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "P", + "span": { + "start": 3587, + "end": 3589 + } + } + ], + "span": { + "start": 3587, + "end": 3590 + } + }, + "span": { + "start": 3589, + "end": 3590 + } + } + ], + "comment": null, + "span": { + "start": 3521, + "end": 3590 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-pause", + "span": { + "start": 3590, + "end": 3619 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3627, + "end": 3632 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Pause", + "span": { + "start": 3635, + "end": 3641 + } + } + ], + "span": { + "start": 3635, + "end": 3641 + } + }, + "span": { + "start": 3640, + "end": 3641 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3646, + "end": 3655 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "P", + "span": { + "start": 3658, + "end": 3660 + } + } + ], + "span": { + "start": 3658, + "end": 3661 + } + }, + "span": { + "start": 3660, + "end": 3661 + } + } + ], + "comment": null, + "span": { + "start": 3590, + "end": 3661 + } + }, + { + "type": "GroupComment", + "content": [ + "" + ], + "span": { + "start": 3661, + "end": 3663 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-mute", + "span": { + "start": 3665, + "end": 3693 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3701, + "end": 3706 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Mute", + "span": { + "start": 3709, + "end": 3714 + } + } + ], + "span": { + "start": 3709, + "end": 3714 + } + }, + "span": { + "start": 3713, + "end": 3714 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3719, + "end": 3728 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "M", + "span": { + "start": 3731, + "end": 3733 + } + } + ], + "span": { + "start": 3731, + "end": 3734 + } + }, + "span": { + "start": 3733, + "end": 3734 + } + } + ], + "comment": null, + "span": { + "start": 3665, + "end": 3734 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-unmute", + "span": { + "start": 3734, + "end": 3764 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3772, + "end": 3777 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Unmute", + "span": { + "start": 3780, + "end": 3787 + } + } + ], + "span": { + "start": 3780, + "end": 3787 + } + }, + "span": { + "start": 3786, + "end": 3787 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3792, + "end": 3801 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "m", + "span": { + "start": 3804, + "end": 3806 + } + } + ], + "span": { + "start": 3804, + "end": 3807 + } + }, + "span": { + "start": 3806, + "end": 3807 + } + } + ], + "comment": null, + "span": { + "start": 3734, + "end": 3807 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-play-speed", + "span": { + "start": 3807, + "end": 3841 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3849, + "end": 3854 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Play Speed", + "span": { + "start": 3857, + "end": 3868 + } + } + ], + "span": { + "start": 3857, + "end": 3868 + } + }, + "span": { + "start": 3867, + "end": 3868 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3873, + "end": 3882 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "d", + "span": { + "start": 3885, + "end": 3887 + } + } + ], + "span": { + "start": 3885, + "end": 3888 + } + }, + "span": { + "start": 3887, + "end": 3888 + } + } + ], + "comment": null, + "span": { + "start": 3807, + "end": 3888 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-play-speed-slow", + "span": { + "start": 3888, + "end": 3927 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3935, + "end": 3940 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Slow (0.5×)", + "span": { + "start": 3943, + "end": 3956 + } + } + ], + "span": { + "start": 3943, + "end": 3956 + } + }, + "span": { + "start": 3955, + "end": 3956 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3961, + "end": 3970 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "S", + "span": { + "start": 3973, + "end": 3975 + } + } + ], + "span": { + "start": 3973, + "end": 3976 + } + }, + "span": { + "start": 3975, + "end": 3976 + } + } + ], + "comment": null, + "span": { + "start": 3888, + "end": 3976 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-play-speed-normal", + "span": { + "start": 3976, + "end": 4017 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4025, + "end": 4030 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Normal", + "span": { + "start": 4033, + "end": 4040 + } + } + ], + "span": { + "start": 4033, + "end": 4040 + } + }, + "span": { + "start": 4039, + "end": 4040 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4045, + "end": 4054 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "N", + "span": { + "start": 4057, + "end": 4059 + } + } + ], + "span": { + "start": 4057, + "end": 4060 + } + }, + "span": { + "start": 4059, + "end": 4060 + } + } + ], + "comment": null, + "span": { + "start": 3976, + "end": 4060 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-play-speed-fast", + "span": { + "start": 4060, + "end": 4099 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4107, + "end": 4112 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Fast (1.25×)", + "span": { + "start": 4115, + "end": 4129 + } + } + ], + "span": { + "start": 4115, + "end": 4129 + } + }, + "span": { + "start": 4128, + "end": 4129 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4134, + "end": 4143 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 4146, + "end": 4148 + } + } + ], + "span": { + "start": 4146, + "end": 4149 + } + }, + "span": { + "start": 4148, + "end": 4149 + } + } + ], + "comment": null, + "span": { + "start": 4060, + "end": 4149 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-play-speed-faster", + "span": { + "start": 4149, + "end": 4190 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4198, + "end": 4203 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Faster (1.5×)", + "span": { + "start": 4206, + "end": 4221 + } + } + ], + "span": { + "start": 4206, + "end": 4221 + } + }, + "span": { + "start": 4220, + "end": 4221 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4226, + "end": 4235 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "a", + "span": { + "start": 4238, + "end": 4240 + } + } + ], + "span": { + "start": 4238, + "end": 4241 + } + }, + "span": { + "start": 4240, + "end": 4241 + } + } + ], + "comment": null, + "span": { + "start": 4149, + "end": 4241 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-play-speed-fastest", + "span": { + "start": 4349, + "end": 4391 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4399, + "end": 4404 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Ludicrous (2×)", + "span": { + "start": 4407, + "end": 4423 + } + } + ], + "span": { + "start": 4407, + "end": 4423 + } + }, + "span": { + "start": 4422, + "end": 4423 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4428, + "end": 4437 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "L", + "span": { + "start": 4440, + "end": 4442 + } + } + ], + "span": { + "start": 4440, + "end": 4443 + } + }, + "span": { + "start": 4442, + "end": 4443 + } + } + ], + "comment": { + "content": [ + "\"Ludicrous\" is a reference to the movie \"Space Balls\" and is meant", + "to say that this speed is very fast." + ], + "span": { + "start": 4241, + "end": 4348 + } + }, + "span": { + "start": 4349, + "end": 4443 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-loop", + "span": { + "start": 4443, + "end": 4471 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4479, + "end": 4484 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Loop", + "span": { + "start": 4487, + "end": 4492 + } + } + ], + "span": { + "start": 4487, + "end": 4492 + } + }, + "span": { + "start": 4491, + "end": 4492 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4497, + "end": 4506 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "L", + "span": { + "start": 4509, + "end": 4511 + } + } + ], + "span": { + "start": 4509, + "end": 4512 + } + }, + "span": { + "start": 4511, + "end": 4512 + } + } + ], + "comment": null, + "span": { + "start": 4443, + "end": 4512 + } + }, + { + "type": "GroupComment", + "content": [ + "The access keys for \"Show Controls\" and \"Hide Controls\" are the same", + "because the two context-menu items are mutually exclusive." + ], + "span": { + "start": 4512, + "end": 4645 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-show-controls", + "span": { + "start": 4647, + "end": 4684 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4692, + "end": 4697 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Show Controls", + "span": { + "start": 4700, + "end": 4714 + } + } + ], + "span": { + "start": 4700, + "end": 4714 + } + }, + "span": { + "start": 4713, + "end": 4714 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4719, + "end": 4728 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "C", + "span": { + "start": 4731, + "end": 4733 + } + } + ], + "span": { + "start": 4731, + "end": 4734 + } + }, + "span": { + "start": 4733, + "end": 4734 + } + } + ], + "comment": null, + "span": { + "start": 4647, + "end": 4734 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-hide-controls", + "span": { + "start": 4734, + "end": 4771 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4779, + "end": 4784 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Hide Controls", + "span": { + "start": 4787, + "end": 4801 + } + } + ], + "span": { + "start": 4787, + "end": 4801 + } + }, + "span": { + "start": 4800, + "end": 4801 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4806, + "end": 4815 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "C", + "span": { + "start": 4818, + "end": 4820 + } + } + ], + "span": { + "start": 4818, + "end": 4821 + } + }, + "span": { + "start": 4820, + "end": 4821 + } + } + ], + "comment": null, + "span": { + "start": 4734, + "end": 4821 + } + }, + { + "type": "GroupComment", + "content": [ + "" + ], + "span": { + "start": 4821, + "end": 4823 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-video-fullscreen", + "span": { + "start": 4825, + "end": 4865 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4873, + "end": 4878 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Full Screen", + "span": { + "start": 4881, + "end": 4893 + } + } + ], + "span": { + "start": 4881, + "end": 4893 + } + }, + "span": { + "start": 4892, + "end": 4893 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4898, + "end": 4907 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 4910, + "end": 4912 + } + } + ], + "span": { + "start": 4910, + "end": 4913 + } + }, + "span": { + "start": 4912, + "end": 4913 + } + } + ], + "comment": null, + "span": { + "start": 4825, + "end": 4913 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-video-leave-fullscreen", + "span": { + "start": 4913, + "end": 4959 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4967, + "end": 4972 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Exit Full Screen", + "span": { + "start": 4975, + "end": 4992 + } + } + ], + "span": { + "start": 4975, + "end": 4992 + } + }, + "span": { + "start": 4991, + "end": 4992 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4997, + "end": 5006 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "u", + "span": { + "start": 5009, + "end": 5011 + } + } + ], + "span": { + "start": 5009, + "end": 5012 + } + }, + "span": { + "start": 5011, + "end": 5012 + } + } + ], + "comment": null, + "span": { + "start": 4913, + "end": 5012 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-media-pip", + "span": { + "start": 5128, + "end": 5155 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5163, + "end": 5168 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Picture-in-Picture", + "span": { + "start": 5171, + "end": 5190 + } + } + ], + "span": { + "start": 5171, + "end": 5190 + } + }, + "span": { + "start": 5189, + "end": 5190 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5195, + "end": 5204 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "u", + "span": { + "start": 5207, + "end": 5209 + } + } + ], + "span": { + "start": 5207, + "end": 5210 + } + }, + "span": { + "start": 5209, + "end": 5210 + } + } + ], + "comment": { + "content": [ + "This is used when right-clicking on a video in the", + "content area when the Picture-in-Picture feature is enabled." + ], + "span": { + "start": 5012, + "end": 5127 + } + }, + "span": { + "start": 5128, + "end": 5210 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-image-reload", + "span": { + "start": 5210, + "end": 5240 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5248, + "end": 5253 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Reload Image", + "span": { + "start": 5256, + "end": 5269 + } + } + ], + "span": { + "start": 5256, + "end": 5269 + } + }, + "span": { + "start": 5268, + "end": 5269 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5274, + "end": 5283 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 5286, + "end": 5288 + } + } + ], + "span": { + "start": 5286, + "end": 5289 + } + }, + "span": { + "start": 5288, + "end": 5289 + } + } + ], + "comment": null, + "span": { + "start": 5210, + "end": 5289 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-image-view", + "span": { + "start": 5289, + "end": 5317 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5325, + "end": 5330 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View Image", + "span": { + "start": 5333, + "end": 5344 + } + } + ], + "span": { + "start": 5333, + "end": 5344 + } + }, + "span": { + "start": 5343, + "end": 5344 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5349, + "end": 5358 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "I", + "span": { + "start": 5361, + "end": 5363 + } + } + ], + "span": { + "start": 5361, + "end": 5364 + } + }, + "span": { + "start": 5363, + "end": 5364 + } + } + ], + "comment": null, + "span": { + "start": 5289, + "end": 5364 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-video-view", + "span": { + "start": 5364, + "end": 5392 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5400, + "end": 5405 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View Video", + "span": { + "start": 5408, + "end": 5419 + } + } + ], + "span": { + "start": 5408, + "end": 5419 + } + }, + "span": { + "start": 5418, + "end": 5419 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5424, + "end": 5433 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "i", + "span": { + "start": 5436, + "end": 5438 + } + } + ], + "span": { + "start": 5436, + "end": 5439 + } + }, + "span": { + "start": 5438, + "end": 5439 + } + } + ], + "comment": null, + "span": { + "start": 5364, + "end": 5439 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-image-copy", + "span": { + "start": 5439, + "end": 5467 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5475, + "end": 5480 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Copy Image", + "span": { + "start": 5483, + "end": 5494 + } + } + ], + "span": { + "start": 5483, + "end": 5494 + } + }, + "span": { + "start": 5493, + "end": 5494 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5499, + "end": 5508 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "y", + "span": { + "start": 5511, + "end": 5513 + } + } + ], + "span": { + "start": 5511, + "end": 5514 + } + }, + "span": { + "start": 5513, + "end": 5514 + } + } + ], + "comment": null, + "span": { + "start": 5439, + "end": 5514 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-image-copy-location", + "span": { + "start": 5514, + "end": 5551 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5559, + "end": 5564 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Copy Image Location", + "span": { + "start": 5567, + "end": 5587 + } + } + ], + "span": { + "start": 5567, + "end": 5587 + } + }, + "span": { + "start": 5586, + "end": 5587 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5592, + "end": 5601 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "o", + "span": { + "start": 5604, + "end": 5606 + } + } + ], + "span": { + "start": 5604, + "end": 5607 + } + }, + "span": { + "start": 5606, + "end": 5607 + } + } + ], + "comment": null, + "span": { + "start": 5514, + "end": 5607 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-video-copy-location", + "span": { + "start": 5607, + "end": 5644 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5652, + "end": 5657 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Copy Video Location", + "span": { + "start": 5660, + "end": 5680 + } + } + ], + "span": { + "start": 5660, + "end": 5680 + } + }, + "span": { + "start": 5679, + "end": 5680 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5685, + "end": 5694 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "o", + "span": { + "start": 5697, + "end": 5699 + } + } + ], + "span": { + "start": 5697, + "end": 5700 + } + }, + "span": { + "start": 5699, + "end": 5700 + } + } + ], + "comment": null, + "span": { + "start": 5607, + "end": 5700 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-audio-copy-location", + "span": { + "start": 5700, + "end": 5737 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5745, + "end": 5750 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Copy Audio Location", + "span": { + "start": 5753, + "end": 5773 + } + } + ], + "span": { + "start": 5753, + "end": 5773 + } + }, + "span": { + "start": 5772, + "end": 5773 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5778, + "end": 5787 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "o", + "span": { + "start": 5790, + "end": 5792 + } + } + ], + "span": { + "start": 5790, + "end": 5793 + } + }, + "span": { + "start": 5792, + "end": 5793 + } + } + ], + "comment": null, + "span": { + "start": 5700, + "end": 5793 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-image-save-as", + "span": { + "start": 5793, + "end": 5824 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5832, + "end": 5837 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Save Image As…", + "span": { + "start": 5840, + "end": 5857 + } + } + ], + "span": { + "start": 5840, + "end": 5857 + } + }, + "span": { + "start": 5856, + "end": 5857 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5862, + "end": 5871 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "v", + "span": { + "start": 5874, + "end": 5876 + } + } + ], + "span": { + "start": 5874, + "end": 5877 + } + }, + "span": { + "start": 5876, + "end": 5877 + } + } + ], + "comment": null, + "span": { + "start": 5793, + "end": 5877 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-image-email", + "span": { + "start": 5877, + "end": 5906 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5914, + "end": 5919 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Email Image…", + "span": { + "start": 5922, + "end": 5937 + } + } + ], + "span": { + "start": 5922, + "end": 5937 + } + }, + "span": { + "start": 5936, + "end": 5937 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5942, + "end": 5951 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "g", + "span": { + "start": 5954, + "end": 5956 + } + } + ], + "span": { + "start": 5954, + "end": 5957 + } + }, + "span": { + "start": 5956, + "end": 5957 + } + } + ], + "comment": null, + "span": { + "start": 5877, + "end": 5957 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-image-set-as-background", + "span": { + "start": 5957, + "end": 5998 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6006, + "end": 6011 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Set As Desktop Background…", + "span": { + "start": 6014, + "end": 6043 + } + } + ], + "span": { + "start": 6014, + "end": 6043 + } + }, + "span": { + "start": 6042, + "end": 6043 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6048, + "end": 6057 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "S", + "span": { + "start": 6060, + "end": 6062 + } + } + ], + "span": { + "start": 6060, + "end": 6063 + } + }, + "span": { + "start": 6062, + "end": 6063 + } + } + ], + "comment": null, + "span": { + "start": 5957, + "end": 6063 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-image-info", + "span": { + "start": 6063, + "end": 6091 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6099, + "end": 6104 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View Image Info", + "span": { + "start": 6107, + "end": 6123 + } + } + ], + "span": { + "start": 6107, + "end": 6123 + } + }, + "span": { + "start": 6122, + "end": 6123 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6128, + "end": 6137 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "f", + "span": { + "start": 6140, + "end": 6142 + } + } + ], + "span": { + "start": 6140, + "end": 6143 + } + }, + "span": { + "start": 6142, + "end": 6143 + } + } + ], + "comment": null, + "span": { + "start": 6063, + "end": 6143 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-image-desc", + "span": { + "start": 6143, + "end": 6171 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6179, + "end": 6184 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View Description", + "span": { + "start": 6187, + "end": 6204 + } + } + ], + "span": { + "start": 6187, + "end": 6204 + } + }, + "span": { + "start": 6203, + "end": 6204 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6209, + "end": 6218 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 6221, + "end": 6223 + } + } + ], + "span": { + "start": 6221, + "end": 6224 + } + }, + "span": { + "start": 6223, + "end": 6224 + } + } + ], + "comment": null, + "span": { + "start": 6143, + "end": 6224 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-video-save-as", + "span": { + "start": 6224, + "end": 6255 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6263, + "end": 6268 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Save Video As…", + "span": { + "start": 6271, + "end": 6288 + } + } + ], + "span": { + "start": 6271, + "end": 6288 + } + }, + "span": { + "start": 6287, + "end": 6288 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6293, + "end": 6302 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "v", + "span": { + "start": 6305, + "end": 6307 + } + } + ], + "span": { + "start": 6305, + "end": 6308 + } + }, + "span": { + "start": 6307, + "end": 6308 + } + } + ], + "comment": null, + "span": { + "start": 6224, + "end": 6308 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-audio-save-as", + "span": { + "start": 6308, + "end": 6339 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6347, + "end": 6352 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Save Audio As…", + "span": { + "start": 6355, + "end": 6372 + } + } + ], + "span": { + "start": 6355, + "end": 6372 + } + }, + "span": { + "start": 6371, + "end": 6372 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6377, + "end": 6386 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "v", + "span": { + "start": 6389, + "end": 6391 + } + } + ], + "span": { + "start": 6389, + "end": 6392 + } + }, + "span": { + "start": 6391, + "end": 6392 + } + } + ], + "comment": null, + "span": { + "start": 6308, + "end": 6392 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-video-image-save-as", + "span": { + "start": 6392, + "end": 6429 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6437, + "end": 6442 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Save Snapshot As…", + "span": { + "start": 6445, + "end": 6465 + } + } + ], + "span": { + "start": 6445, + "end": 6465 + } + }, + "span": { + "start": 6464, + "end": 6465 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6470, + "end": 6479 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "S", + "span": { + "start": 6482, + "end": 6484 + } + } + ], + "span": { + "start": 6482, + "end": 6485 + } + }, + "span": { + "start": 6484, + "end": 6485 + } + } + ], + "comment": null, + "span": { + "start": 6392, + "end": 6485 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-video-email", + "span": { + "start": 6485, + "end": 6514 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6522, + "end": 6527 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Email Video…", + "span": { + "start": 6530, + "end": 6545 + } + } + ], + "span": { + "start": 6530, + "end": 6545 + } + }, + "span": { + "start": 6544, + "end": 6545 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6550, + "end": 6559 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "a", + "span": { + "start": 6562, + "end": 6564 + } + } + ], + "span": { + "start": 6562, + "end": 6565 + } + }, + "span": { + "start": 6564, + "end": 6565 + } + } + ], + "comment": null, + "span": { + "start": 6485, + "end": 6565 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-audio-email", + "span": { + "start": 6565, + "end": 6594 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6602, + "end": 6607 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Email Audio…", + "span": { + "start": 6610, + "end": 6625 + } + } + ], + "span": { + "start": 6610, + "end": 6625 + } + }, + "span": { + "start": 6624, + "end": 6625 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6630, + "end": 6639 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "a", + "span": { + "start": 6642, + "end": 6644 + } + } + ], + "span": { + "start": 6642, + "end": 6645 + } + }, + "span": { + "start": 6644, + "end": 6645 + } + } + ], + "comment": null, + "span": { + "start": 6565, + "end": 6645 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-plugin-play", + "span": { + "start": 6645, + "end": 6674 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6682, + "end": 6687 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Activate this plugin", + "span": { + "start": 6690, + "end": 6711 + } + } + ], + "span": { + "start": 6690, + "end": 6711 + } + }, + "span": { + "start": 6710, + "end": 6711 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6716, + "end": 6725 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "c", + "span": { + "start": 6728, + "end": 6730 + } + } + ], + "span": { + "start": 6728, + "end": 6731 + } + }, + "span": { + "start": 6730, + "end": 6731 + } + } + ], + "comment": null, + "span": { + "start": 6645, + "end": 6731 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-plugin-hide", + "span": { + "start": 6731, + "end": 6760 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6768, + "end": 6773 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Hide this plugin", + "span": { + "start": 6776, + "end": 6793 + } + } + ], + "span": { + "start": 6776, + "end": 6793 + } + }, + "span": { + "start": 6792, + "end": 6793 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6798, + "end": 6807 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "H", + "span": { + "start": 6810, + "end": 6812 + } + } + ], + "span": { + "start": 6810, + "end": 6813 + } + }, + "span": { + "start": 6812, + "end": 6813 + } + } + ], + "comment": null, + "span": { + "start": 6731, + "end": 6813 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-save-to-pocket", + "span": { + "start": 6813, + "end": 6845 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6853, + "end": 6858 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Save Page to ", + "span": { + "start": 6861, + "end": 6874 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "pocket-brand-name", + "span": { + "start": 6877, + "end": 6894 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 6876, + "end": 6895 + } + }, + { + "start": 6876, + "end": 6895 + } + ], + "span": { + "start": 6874, + "end": 6895 + } + } + ], + "span": { + "start": 6861, + "end": 6897 + } + }, + "span": { + "start": 6896, + "end": 6897 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6902, + "end": 6911 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "k", + "span": { + "start": 6914, + "end": 6916 + } + } + ], + "span": { + "start": 6914, + "end": 6917 + } + }, + "span": { + "start": 6916, + "end": 6917 + } + } + ], + "comment": null, + "span": { + "start": 6813, + "end": 6917 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-send-to-device", + "span": { + "start": 6917, + "end": 6949 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6957, + "end": 6962 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Send Page to Device", + "span": { + "start": 6965, + "end": 6985 + } + } + ], + "span": { + "start": 6965, + "end": 6985 + } + }, + "span": { + "start": 6984, + "end": 6985 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6990, + "end": 6999 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "n", + "span": { + "start": 7002, + "end": 7004 + } + } + ], + "span": { + "start": 7002, + "end": 7005 + } + }, + "span": { + "start": 7004, + "end": 7005 + } + } + ], + "comment": null, + "span": { + "start": 6917, + "end": 7005 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-view-background-image", + "span": { + "start": 7005, + "end": 7044 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7052, + "end": 7057 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View Background Image", + "span": { + "start": 7060, + "end": 7082 + } + } + ], + "span": { + "start": 7060, + "end": 7082 + } + }, + "span": { + "start": 7081, + "end": 7082 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7087, + "end": 7096 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "w", + "span": { + "start": 7099, + "end": 7101 + } + } + ], + "span": { + "start": 7099, + "end": 7102 + } + }, + "span": { + "start": 7101, + "end": 7102 + } + } + ], + "comment": null, + "span": { + "start": 7005, + "end": 7102 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-generate-new-password", + "span": { + "start": 7102, + "end": 7141 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7149, + "end": 7154 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Use Generated Password…", + "span": { + "start": 7157, + "end": 7183 + } + } + ], + "span": { + "start": 7157, + "end": 7183 + } + }, + "span": { + "start": 7182, + "end": 7183 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7188, + "end": 7197 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "G", + "span": { + "start": 7200, + "end": 7202 + } + } + ], + "span": { + "start": 7200, + "end": 7203 + } + }, + "span": { + "start": 7202, + "end": 7203 + } + } + ], + "comment": null, + "span": { + "start": 7102, + "end": 7203 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-keyword", + "span": { + "start": 7203, + "end": 7228 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7236, + "end": 7241 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Add a Keyword for this Search…", + "span": { + "start": 7244, + "end": 7277 + } + } + ], + "span": { + "start": 7244, + "end": 7277 + } + }, + "span": { + "start": 7276, + "end": 7277 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7282, + "end": 7291 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "K", + "span": { + "start": 7294, + "end": 7296 + } + } + ], + "span": { + "start": 7294, + "end": 7297 + } + }, + "span": { + "start": 7296, + "end": 7297 + } + } + ], + "comment": null, + "span": { + "start": 7203, + "end": 7297 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-link-send-to-device", + "span": { + "start": 7297, + "end": 7334 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7342, + "end": 7347 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Send Link to Device", + "span": { + "start": 7350, + "end": 7370 + } + } + ], + "span": { + "start": 7350, + "end": 7370 + } + }, + "span": { + "start": 7369, + "end": 7370 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7375, + "end": 7384 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "n", + "span": { + "start": 7387, + "end": 7389 + } + } + ], + "span": { + "start": 7387, + "end": 7390 + } + }, + "span": { + "start": 7389, + "end": 7390 + } + } + ], + "comment": null, + "span": { + "start": 7297, + "end": 7390 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-frame", + "span": { + "start": 7390, + "end": 7413 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7421, + "end": 7426 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "This Frame", + "span": { + "start": 7429, + "end": 7440 + } + } + ], + "span": { + "start": 7429, + "end": 7440 + } + }, + "span": { + "start": 7439, + "end": 7440 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7445, + "end": 7454 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "h", + "span": { + "start": 7457, + "end": 7459 + } + } + ], + "span": { + "start": 7457, + "end": 7460 + } + }, + "span": { + "start": 7459, + "end": 7460 + } + } + ], + "comment": null, + "span": { + "start": 7390, + "end": 7460 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-frame-show-this", + "span": { + "start": 7460, + "end": 7493 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7501, + "end": 7506 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Show Only This Frame", + "span": { + "start": 7509, + "end": 7530 + } + } + ], + "span": { + "start": 7509, + "end": 7530 + } + }, + "span": { + "start": 7529, + "end": 7530 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7535, + "end": 7544 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "S", + "span": { + "start": 7547, + "end": 7549 + } + } + ], + "span": { + "start": 7547, + "end": 7550 + } + }, + "span": { + "start": 7549, + "end": 7550 + } + } + ], + "comment": null, + "span": { + "start": 7460, + "end": 7550 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-frame-open-tab", + "span": { + "start": 7550, + "end": 7582 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7590, + "end": 7595 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open Frame in New Tab", + "span": { + "start": 7598, + "end": 7620 + } + } + ], + "span": { + "start": 7598, + "end": 7620 + } + }, + "span": { + "start": 7619, + "end": 7620 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7625, + "end": 7634 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "T", + "span": { + "start": 7637, + "end": 7639 + } + } + ], + "span": { + "start": 7637, + "end": 7640 + } + }, + "span": { + "start": 7639, + "end": 7640 + } + } + ], + "comment": null, + "span": { + "start": 7550, + "end": 7640 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-frame-open-window", + "span": { + "start": 7640, + "end": 7675 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7683, + "end": 7688 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open Frame in New Window", + "span": { + "start": 7691, + "end": 7716 + } + } + ], + "span": { + "start": 7691, + "end": 7716 + } + }, + "span": { + "start": 7715, + "end": 7716 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7721, + "end": 7730 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "W", + "span": { + "start": 7733, + "end": 7735 + } + } + ], + "span": { + "start": 7733, + "end": 7736 + } + }, + "span": { + "start": 7735, + "end": 7736 + } + } + ], + "comment": null, + "span": { + "start": 7640, + "end": 7736 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-frame-reload", + "span": { + "start": 7736, + "end": 7766 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7774, + "end": 7779 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Reload Frame", + "span": { + "start": 7782, + "end": 7795 + } + } + ], + "span": { + "start": 7782, + "end": 7795 + } + }, + "span": { + "start": 7794, + "end": 7795 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7800, + "end": 7809 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 7812, + "end": 7814 + } + } + ], + "span": { + "start": 7812, + "end": 7815 + } + }, + "span": { + "start": 7814, + "end": 7815 + } + } + ], + "comment": null, + "span": { + "start": 7736, + "end": 7815 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-frame-bookmark", + "span": { + "start": 7815, + "end": 7847 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7855, + "end": 7860 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmark This Frame", + "span": { + "start": 7863, + "end": 7883 + } + } + ], + "span": { + "start": 7863, + "end": 7883 + } + }, + "span": { + "start": 7882, + "end": 7883 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7888, + "end": 7897 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "m", + "span": { + "start": 7900, + "end": 7902 + } + } + ], + "span": { + "start": 7900, + "end": 7903 + } + }, + "span": { + "start": 7902, + "end": 7903 + } + } + ], + "comment": null, + "span": { + "start": 7815, + "end": 7903 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-frame-save-as", + "span": { + "start": 7903, + "end": 7934 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 7942, + "end": 7947 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Save Frame As…", + "span": { + "start": 7950, + "end": 7967 + } + } + ], + "span": { + "start": 7950, + "end": 7967 + } + }, + "span": { + "start": 7966, + "end": 7967 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 7972, + "end": 7981 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 7984, + "end": 7986 + } + } + ], + "span": { + "start": 7984, + "end": 7987 + } + }, + "span": { + "start": 7986, + "end": 7987 + } + } + ], + "comment": null, + "span": { + "start": 7903, + "end": 7987 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-frame-print", + "span": { + "start": 7987, + "end": 8016 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8024, + "end": 8029 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Print Frame…", + "span": { + "start": 8032, + "end": 8047 + } + } + ], + "span": { + "start": 8032, + "end": 8047 + } + }, + "span": { + "start": 8046, + "end": 8047 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8052, + "end": 8061 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "P", + "span": { + "start": 8064, + "end": 8066 + } + } + ], + "span": { + "start": 8064, + "end": 8067 + } + }, + "span": { + "start": 8066, + "end": 8067 + } + } + ], + "comment": null, + "span": { + "start": 7987, + "end": 8067 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-frame-view-source", + "span": { + "start": 8067, + "end": 8102 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8110, + "end": 8115 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View Frame Source", + "span": { + "start": 8118, + "end": 8136 + } + } + ], + "span": { + "start": 8118, + "end": 8136 + } + }, + "span": { + "start": 8135, + "end": 8136 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8141, + "end": 8150 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "V", + "span": { + "start": 8153, + "end": 8155 + } + } + ], + "span": { + "start": 8153, + "end": 8156 + } + }, + "span": { + "start": 8155, + "end": 8156 + } + } + ], + "comment": null, + "span": { + "start": 8067, + "end": 8156 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-frame-view-info", + "span": { + "start": 8156, + "end": 8189 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8197, + "end": 8202 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View Frame Info", + "span": { + "start": 8205, + "end": 8221 + } + } + ], + "span": { + "start": 8205, + "end": 8221 + } + }, + "span": { + "start": 8220, + "end": 8221 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8226, + "end": 8235 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "I", + "span": { + "start": 8238, + "end": 8240 + } + } + ], + "span": { + "start": 8238, + "end": 8241 + } + }, + "span": { + "start": 8240, + "end": 8241 + } + } + ], + "comment": null, + "span": { + "start": 8156, + "end": 8241 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-view-selection-source", + "span": { + "start": 8241, + "end": 8280 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8288, + "end": 8293 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View Selection Source", + "span": { + "start": 8296, + "end": 8318 + } + } + ], + "span": { + "start": 8296, + "end": 8318 + } + }, + "span": { + "start": 8317, + "end": 8318 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8323, + "end": 8332 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "e", + "span": { + "start": 8335, + "end": 8337 + } + } + ], + "span": { + "start": 8335, + "end": 8338 + } + }, + "span": { + "start": 8337, + "end": 8338 + } + } + ], + "comment": null, + "span": { + "start": 8241, + "end": 8338 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-view-page-source", + "span": { + "start": 8338, + "end": 8372 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8380, + "end": 8385 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View Page Source", + "span": { + "start": 8388, + "end": 8405 + } + } + ], + "span": { + "start": 8388, + "end": 8405 + } + }, + "span": { + "start": 8404, + "end": 8405 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8410, + "end": 8419 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "V", + "span": { + "start": 8422, + "end": 8424 + } + } + ], + "span": { + "start": 8422, + "end": 8425 + } + }, + "span": { + "start": 8424, + "end": 8425 + } + } + ], + "comment": null, + "span": { + "start": 8338, + "end": 8425 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-view-page-info", + "span": { + "start": 8425, + "end": 8457 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8465, + "end": 8470 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View Page Info", + "span": { + "start": 8473, + "end": 8488 + } + } + ], + "span": { + "start": 8473, + "end": 8488 + } + }, + "span": { + "start": 8487, + "end": 8488 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8493, + "end": 8502 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "I", + "span": { + "start": 8505, + "end": 8507 + } + } + ], + "span": { + "start": 8505, + "end": 8508 + } + }, + "span": { + "start": 8507, + "end": 8508 + } + } + ], + "comment": null, + "span": { + "start": 8425, + "end": 8508 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-bidi-switch-text", + "span": { + "start": 8508, + "end": 8542 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8550, + "end": 8555 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Switch Text Direction", + "span": { + "start": 8558, + "end": 8580 + } + } + ], + "span": { + "start": 8558, + "end": 8580 + } + }, + "span": { + "start": 8579, + "end": 8580 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8585, + "end": 8594 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "w", + "span": { + "start": 8597, + "end": 8599 + } + } + ], + "span": { + "start": 8597, + "end": 8600 + } + }, + "span": { + "start": 8599, + "end": 8600 + } + } + ], + "comment": null, + "span": { + "start": 8508, + "end": 8600 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-bidi-switch-page", + "span": { + "start": 8600, + "end": 8634 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8642, + "end": 8647 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Switch Page Direction", + "span": { + "start": 8650, + "end": 8672 + } + } + ], + "span": { + "start": 8650, + "end": 8672 + } + }, + "span": { + "start": 8671, + "end": 8672 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8677, + "end": 8686 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 8689, + "end": 8691 + } + } + ], + "span": { + "start": 8689, + "end": 8692 + } + }, + "span": { + "start": 8691, + "end": 8692 + } + } + ], + "comment": null, + "span": { + "start": 8600, + "end": 8692 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-inspect-element", + "span": { + "start": 8692, + "end": 8725 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8733, + "end": 8738 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Inspect Element", + "span": { + "start": 8741, + "end": 8757 + } + } + ], + "span": { + "start": 8741, + "end": 8757 + } + }, + "span": { + "start": 8756, + "end": 8757 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8762, + "end": 8771 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Q", + "span": { + "start": 8774, + "end": 8776 + } + } + ], + "span": { + "start": 8774, + "end": 8777 + } + }, + "span": { + "start": 8776, + "end": 8777 + } + } + ], + "comment": null, + "span": { + "start": 8692, + "end": 8777 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-inspect-a11y-properties", + "span": { + "start": 8777, + "end": 8818 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8826, + "end": 8831 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Inspect Accessibility Properties", + "span": { + "start": 8834, + "end": 8867 + } + } + ], + "span": { + "start": 8834, + "end": 8868 + } + }, + "span": { + "start": 8867, + "end": 8868 + } + } + ], + "comment": null, + "span": { + "start": 8777, + "end": 8868 + } + }, + { + "type": "Message", + "id": { + "name": "main-context-menu-eme-learn-more", + "span": { + "start": 8868, + "end": 8900 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 8908, + "end": 8913 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Learn more about DRM…", + "span": { + "start": 8916, + "end": 8940 + } + } + ], + "span": { + "start": 8916, + "end": 8940 + } + }, + "span": { + "start": 8939, + "end": 8940 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 8945, + "end": 8954 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 8957, + "end": 8959 + } + } + ], + "span": { + "start": 8957, + "end": 8959 + } + }, + "span": { + "start": 8958, + "end": 8959 + } + } + ], + "comment": null, + "span": { + "start": 8868, + "end": 8959 + } + } + ], + "span": { + "start": 0, + "end": 8959 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/browserSets.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/browserSets.spans.json new file mode 100644 index 00000000..cc3affba --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/browserSets.spans.json @@ -0,0 +1,2874 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "Message", + "id": { + "name": "window-minimize-command", + "span": { + "start": 200, + "end": 223 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 231, + "end": 236 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Minimize", + "span": { + "start": 239, + "end": 248 + } + } + ], + "span": { + "start": 239, + "end": 249 + } + }, + "span": { + "start": 248, + "end": 249 + } + } + ], + "comment": null, + "span": { + "start": 200, + "end": 249 + } + }, + { + "type": "Message", + "id": { + "name": "window-zoom-command", + "span": { + "start": 249, + "end": 268 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 276, + "end": 281 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Zoom", + "span": { + "start": 284, + "end": 289 + } + } + ], + "span": { + "start": 284, + "end": 290 + } + }, + "span": { + "start": 289, + "end": 290 + } + } + ], + "comment": null, + "span": { + "start": 249, + "end": 290 + } + }, + { + "type": "Message", + "id": { + "name": "window-new-shortcut", + "span": { + "start": 290, + "end": 309 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 317, + "end": 320 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "N", + "span": { + "start": 323, + "end": 325 + } + } + ], + "span": { + "start": 323, + "end": 326 + } + }, + "span": { + "start": 325, + "end": 326 + } + } + ], + "comment": null, + "span": { + "start": 290, + "end": 326 + } + }, + { + "type": "Message", + "id": { + "name": "window-minimize-shortcut", + "span": { + "start": 326, + "end": 350 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 358, + "end": 361 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "M", + "span": { + "start": 364, + "end": 366 + } + } + ], + "span": { + "start": 364, + "end": 367 + } + }, + "span": { + "start": 366, + "end": 367 + } + } + ], + "comment": null, + "span": { + "start": 326, + "end": 367 + } + }, + { + "type": "Message", + "id": { + "name": "close-shortcut", + "span": { + "start": 367, + "end": 381 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 389, + "end": 392 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "W", + "span": { + "start": 395, + "end": 397 + } + } + ], + "span": { + "start": 395, + "end": 398 + } + }, + "span": { + "start": 397, + "end": 398 + } + } + ], + "comment": null, + "span": { + "start": 367, + "end": 398 + } + }, + { + "type": "Message", + "id": { + "name": "tab-new-shortcut", + "span": { + "start": 398, + "end": 414 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 422, + "end": 425 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "T", + "span": { + "start": 428, + "end": 430 + } + } + ], + "span": { + "start": 428, + "end": 431 + } + }, + "span": { + "start": 430, + "end": 431 + } + } + ], + "comment": null, + "span": { + "start": 398, + "end": 431 + } + }, + { + "type": "Message", + "id": { + "name": "location-open-shortcut", + "span": { + "start": 431, + "end": 453 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 461, + "end": 464 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "L", + "span": { + "start": 467, + "end": 469 + } + } + ], + "span": { + "start": 467, + "end": 470 + } + }, + "span": { + "start": 469, + "end": 470 + } + } + ], + "comment": null, + "span": { + "start": 431, + "end": 470 + } + }, + { + "type": "Message", + "id": { + "name": "location-open-shortcut-alt", + "span": { + "start": 470, + "end": 496 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 504, + "end": 507 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 510, + "end": 512 + } + } + ], + "span": { + "start": 510, + "end": 513 + } + }, + "span": { + "start": 512, + "end": 513 + } + } + ], + "comment": null, + "span": { + "start": 470, + "end": 513 + } + }, + { + "type": "Message", + "id": { + "name": "search-focus-shortcut", + "span": { + "start": 513, + "end": 534 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 542, + "end": 545 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "K", + "span": { + "start": 548, + "end": 550 + } + } + ], + "span": { + "start": 548, + "end": 551 + } + }, + "span": { + "start": 550, + "end": 551 + } + } + ], + "comment": null, + "span": { + "start": 513, + "end": 551 + } + }, + { + "type": "Message", + "id": { + "name": "find-shortcut", + "span": { + "start": 628, + "end": 641 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 649, + "end": 652 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 655, + "end": 657 + } + } + ], + "span": { + "start": 655, + "end": 658 + } + }, + "span": { + "start": 657, + "end": 658 + } + } + ], + "comment": { + "content": [ + "This shortcut is used in two contexts:", + " - web search", + " - find in page" + ], + "span": { + "start": 551, + "end": 627 + } + }, + "span": { + "start": 628, + "end": 658 + } + }, + { + "type": "Message", + "id": { + "name": "search-find-again-shortcut", + "span": { + "start": 658, + "end": 684 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 692, + "end": 695 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "G", + "span": { + "start": 698, + "end": 700 + } + } + ], + "span": { + "start": 698, + "end": 701 + } + }, + "span": { + "start": 700, + "end": 701 + } + } + ], + "comment": null, + "span": { + "start": 658, + "end": 701 + } + }, + { + "type": "Message", + "id": { + "name": "search-find-again-shortcut-alt", + "span": { + "start": 701, + "end": 731 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "keycode", + "span": { + "start": 739, + "end": 746 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "VK_F3", + "span": { + "start": 749, + "end": 755 + } + } + ], + "span": { + "start": 749, + "end": 756 + } + }, + "span": { + "start": 755, + "end": 756 + } + } + ], + "comment": null, + "span": { + "start": 701, + "end": 756 + } + }, + { + "type": "Message", + "id": { + "name": "search-find-selection-shortcut", + "span": { + "start": 756, + "end": 786 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 794, + "end": 797 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "E", + "span": { + "start": 800, + "end": 802 + } + } + ], + "span": { + "start": 800, + "end": 803 + } + }, + "span": { + "start": 802, + "end": 803 + } + } + ], + "comment": null, + "span": { + "start": 756, + "end": 803 + } + }, + { + "type": "Message", + "id": { + "name": "search-focus-shortcut-alt", + "span": { + "start": 933, + "end": 958 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 966, + "end": 969 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "PLATFORM", + "span": { + "start": 974, + "end": 982 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 982, + "end": 984 + } + }, + "span": { + "start": 974, + "end": 984 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "linux", + "span": { + "start": 997, + "end": 1002 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "J", + "span": { + "start": 1004, + "end": 1006 + } + } + ], + "span": { + "start": 1004, + "end": 1006 + } + }, + "default": false, + "span": { + "start": 996, + "end": 1006 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 1015, + "end": 1020 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "E", + "span": { + "start": 1022, + "end": 1024 + } + } + ], + "span": { + "start": 1022, + "end": 1024 + } + }, + "default": true, + "span": { + "start": 1013, + "end": 1024 + } + } + ], + "span": { + "start": 974, + "end": 1028 + } + }, + "span": { + "start": 972, + "end": 1028 + } + } + ], + "span": { + "start": 972, + "end": 1031 + } + }, + "span": { + "start": 1030, + "end": 1031 + } + } + ], + "comment": { + "content": [ + "Verify what shortcut for that operation", + "are recommended by the Human Interface Guidelines", + "of each platform for your locale." + ], + "span": { + "start": 803, + "end": 932 + } + }, + "span": { + "start": 933, + "end": 1031 + } + }, + { + "type": "Message", + "id": { + "name": "downloads-shortcut", + "span": { + "start": 1161, + "end": 1179 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1187, + "end": 1190 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "PLATFORM", + "span": { + "start": 1195, + "end": 1203 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 1203, + "end": 1205 + } + }, + "span": { + "start": 1195, + "end": 1205 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "linux", + "span": { + "start": 1218, + "end": 1223 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Y", + "span": { + "start": 1225, + "end": 1227 + } + } + ], + "span": { + "start": 1225, + "end": 1227 + } + }, + "default": false, + "span": { + "start": 1217, + "end": 1227 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 1236, + "end": 1241 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "J", + "span": { + "start": 1243, + "end": 1245 + } + } + ], + "span": { + "start": 1243, + "end": 1245 + } + }, + "default": true, + "span": { + "start": 1234, + "end": 1245 + } + } + ], + "span": { + "start": 1195, + "end": 1249 + } + }, + "span": { + "start": 1193, + "end": 1249 + } + } + ], + "span": { + "start": 1193, + "end": 1252 + } + }, + "span": { + "start": 1251, + "end": 1252 + } + } + ], + "comment": { + "content": [ + "Verify what shortcut for that operation", + "are recommended by the Human Interface Guidelines", + "of each platform for your locale." + ], + "span": { + "start": 1031, + "end": 1160 + } + }, + "span": { + "start": 1161, + "end": 1252 + } + }, + { + "type": "Message", + "id": { + "name": "addons-shortcut", + "span": { + "start": 1252, + "end": 1267 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1275, + "end": 1278 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A", + "span": { + "start": 1281, + "end": 1283 + } + } + ], + "span": { + "start": 1281, + "end": 1284 + } + }, + "span": { + "start": 1283, + "end": 1284 + } + } + ], + "comment": null, + "span": { + "start": 1252, + "end": 1284 + } + }, + { + "type": "Message", + "id": { + "name": "file-open-shortcut", + "span": { + "start": 1284, + "end": 1302 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1310, + "end": 1313 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "O", + "span": { + "start": 1316, + "end": 1318 + } + } + ], + "span": { + "start": 1316, + "end": 1319 + } + }, + "span": { + "start": 1318, + "end": 1319 + } + } + ], + "comment": null, + "span": { + "start": 1284, + "end": 1319 + } + }, + { + "type": "Message", + "id": { + "name": "save-page-shortcut", + "span": { + "start": 1319, + "end": 1337 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1345, + "end": 1348 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "S", + "span": { + "start": 1351, + "end": 1353 + } + } + ], + "span": { + "start": 1351, + "end": 1354 + } + }, + "span": { + "start": 1353, + "end": 1354 + } + } + ], + "comment": null, + "span": { + "start": 1319, + "end": 1354 + } + }, + { + "type": "Message", + "id": { + "name": "page-source-shortcut", + "span": { + "start": 1354, + "end": 1374 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1382, + "end": 1385 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "U", + "span": { + "start": 1388, + "end": 1390 + } + } + ], + "span": { + "start": 1388, + "end": 1391 + } + }, + "span": { + "start": 1390, + "end": 1391 + } + } + ], + "comment": null, + "span": { + "start": 1354, + "end": 1391 + } + }, + { + "type": "Message", + "id": { + "name": "page-source-shortcut-safari", + "span": { + "start": 1715, + "end": 1742 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1750, + "end": 1753 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "U", + "span": { + "start": 1756, + "end": 1758 + } + } + ], + "span": { + "start": 1756, + "end": 1759 + } + }, + "span": { + "start": 1758, + "end": 1759 + } + } + ], + "comment": { + "content": [ + "This should match the Option+Command keyboard shortcut letter that Safari", + "and Chrome use for \"View Source\" on macOS. `page-source-shortcut` above", + "is Firefox's official keyboard shortcut shown in the GUI.", + "Safari variant is an alias provided for the convenience of Safari and Chrome", + "users on macOS. See bug 1398988." + ], + "span": { + "start": 1391, + "end": 1714 + } + }, + "span": { + "start": 1715, + "end": 1759 + } + }, + { + "type": "Message", + "id": { + "name": "page-info-shortcut", + "span": { + "start": 1759, + "end": 1777 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1785, + "end": 1788 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "I", + "span": { + "start": 1791, + "end": 1793 + } + } + ], + "span": { + "start": 1791, + "end": 1794 + } + }, + "span": { + "start": 1793, + "end": 1794 + } + } + ], + "comment": null, + "span": { + "start": 1759, + "end": 1794 + } + }, + { + "type": "Message", + "id": { + "name": "print-shortcut", + "span": { + "start": 1794, + "end": 1808 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1816, + "end": 1819 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "P", + "span": { + "start": 1822, + "end": 1824 + } + } + ], + "span": { + "start": 1822, + "end": 1825 + } + }, + "span": { + "start": 1824, + "end": 1825 + } + } + ], + "comment": null, + "span": { + "start": 1794, + "end": 1825 + } + }, + { + "type": "Message", + "id": { + "name": "mute-toggle-shortcut", + "span": { + "start": 1825, + "end": 1845 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1853, + "end": 1856 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "M", + "span": { + "start": 1859, + "end": 1861 + } + } + ], + "span": { + "start": 1859, + "end": 1862 + } + }, + "span": { + "start": 1861, + "end": 1862 + } + } + ], + "comment": null, + "span": { + "start": 1825, + "end": 1862 + } + }, + { + "type": "Message", + "id": { + "name": "nav-back-shortcut-alt", + "span": { + "start": 1862, + "end": 1883 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1891, + "end": 1894 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "[", + "span": { + "start": 1897, + "end": 1899 + } + } + ], + "span": { + "start": 1897, + "end": 1900 + } + }, + "span": { + "start": 1899, + "end": 1900 + } + } + ], + "comment": null, + "span": { + "start": 1862, + "end": 1900 + } + }, + { + "type": "Message", + "id": { + "name": "nav-fwd-shortcut-alt", + "span": { + "start": 1900, + "end": 1920 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1928, + "end": 1931 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "]", + "span": { + "start": 1934, + "end": 1936 + } + } + ], + "span": { + "start": 1934, + "end": 1937 + } + }, + "span": { + "start": 1936, + "end": 1937 + } + } + ], + "comment": null, + "span": { + "start": 1900, + "end": 1937 + } + }, + { + "type": "Message", + "id": { + "name": "nav-reload-shortcut", + "span": { + "start": 1937, + "end": 1956 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 1964, + "end": 1967 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 1970, + "end": 1972 + } + } + ], + "span": { + "start": 1970, + "end": 1973 + } + }, + "span": { + "start": 1972, + "end": 1973 + } + } + ], + "comment": null, + "span": { + "start": 1937, + "end": 1973 + } + }, + { + "type": "Message", + "id": { + "name": "nav-stop-shortcut", + "span": { + "start": 2009, + "end": 2026 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 2034, + "end": 2037 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": ".", + "span": { + "start": 2040, + "end": 2042 + } + } + ], + "span": { + "start": 2040, + "end": 2043 + } + }, + "span": { + "start": 2042, + "end": 2043 + } + } + ], + "comment": { + "content": [ + "Shortcut available only on macOS." + ], + "span": { + "start": 1973, + "end": 2008 + } + }, + "span": { + "start": 2009, + "end": 2043 + } + }, + { + "type": "Message", + "id": { + "name": "history-show-all-shortcut", + "span": { + "start": 2043, + "end": 2068 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 2076, + "end": 2079 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "H", + "span": { + "start": 2082, + "end": 2084 + } + } + ], + "span": { + "start": 2082, + "end": 2085 + } + }, + "span": { + "start": 2084, + "end": 2085 + } + } + ], + "comment": null, + "span": { + "start": 2043, + "end": 2085 + } + }, + { + "type": "Message", + "id": { + "name": "history-sidebar-shortcut", + "span": { + "start": 2085, + "end": 2109 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 2117, + "end": 2120 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "H", + "span": { + "start": 2123, + "end": 2125 + } + } + ], + "span": { + "start": 2123, + "end": 2126 + } + }, + "span": { + "start": 2125, + "end": 2126 + } + } + ], + "comment": null, + "span": { + "start": 2085, + "end": 2126 + } + }, + { + "type": "Message", + "id": { + "name": "full-screen-shortcut", + "span": { + "start": 2126, + "end": 2146 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 2154, + "end": 2157 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 2160, + "end": 2162 + } + } + ], + "span": { + "start": 2160, + "end": 2163 + } + }, + "span": { + "start": 2162, + "end": 2163 + } + } + ], + "comment": null, + "span": { + "start": 2126, + "end": 2163 + } + }, + { + "type": "Message", + "id": { + "name": "reader-mode-toggle-shortcut-windows", + "span": { + "start": 2163, + "end": 2198 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "keycode", + "span": { + "start": 2206, + "end": 2213 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "VK_F9", + "span": { + "start": 2216, + "end": 2222 + } + } + ], + "span": { + "start": 2216, + "end": 2223 + } + }, + "span": { + "start": 2222, + "end": 2223 + } + } + ], + "comment": null, + "span": { + "start": 2163, + "end": 2223 + } + }, + { + "type": "Message", + "id": { + "name": "reader-mode-toggle-shortcut-other", + "span": { + "start": 2223, + "end": 2256 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 2264, + "end": 2267 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 2270, + "end": 2272 + } + } + ], + "span": { + "start": 2270, + "end": 2273 + } + }, + "span": { + "start": 2272, + "end": 2273 + } + } + ], + "comment": null, + "span": { + "start": 2223, + "end": 2273 + } + }, + { + "type": "Message", + "id": { + "name": "picture-in-picture-toggle-shortcut", + "span": { + "start": 2273, + "end": 2307 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 2315, + "end": 2318 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "]", + "span": { + "start": 2321, + "end": 2323 + } + } + ], + "span": { + "start": 2321, + "end": 2324 + } + }, + "span": { + "start": 2323, + "end": 2324 + } + } + ], + "comment": null, + "span": { + "start": 2273, + "end": 2324 + } + }, + { + "type": "Message", + "id": { + "name": "picture-in-picture-toggle-shortcut-alt", + "span": { + "start": 2445, + "end": 2483 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 2491, + "end": 2494 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "}", + "span": { + "start": 2498, + "end": 2501 + } + }, + { + "start": 2498, + "end": 2501 + } + ], + "span": { + "start": 2497, + "end": 2501 + } + } + ], + "span": { + "start": 2497, + "end": 2504 + } + }, + "span": { + "start": 2503, + "end": 2504 + } + } + ], + "comment": { + "content": [ + "Pick the key that is commonly present", + "in your locale keyboards above the", + "`picture-in-picture-toggle-shortcut` key." + ], + "span": { + "start": 2324, + "end": 2444 + } + }, + "span": { + "start": 2445, + "end": 2504 + } + }, + { + "type": "Message", + "id": { + "name": "bookmark-this-page-shortcut", + "span": { + "start": 2504, + "end": 2531 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 2539, + "end": 2542 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 2545, + "end": 2547 + } + } + ], + "span": { + "start": 2545, + "end": 2548 + } + }, + "span": { + "start": 2547, + "end": 2548 + } + } + ], + "comment": null, + "span": { + "start": 2504, + "end": 2548 + } + }, + { + "type": "Message", + "id": { + "name": "bookmark-show-all-shortcut", + "span": { + "start": 2678, + "end": 2704 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 2712, + "end": 2715 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "PLATFORM", + "span": { + "start": 2720, + "end": 2728 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 2728, + "end": 2730 + } + }, + "span": { + "start": 2720, + "end": 2730 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "linux", + "span": { + "start": 2743, + "end": 2748 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "O", + "span": { + "start": 2750, + "end": 2752 + } + } + ], + "span": { + "start": 2750, + "end": 2752 + } + }, + "default": false, + "span": { + "start": 2742, + "end": 2752 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 2761, + "end": 2766 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "B", + "span": { + "start": 2768, + "end": 2770 + } + } + ], + "span": { + "start": 2768, + "end": 2770 + } + }, + "default": true, + "span": { + "start": 2759, + "end": 2770 + } + } + ], + "span": { + "start": 2720, + "end": 2774 + } + }, + "span": { + "start": 2718, + "end": 2774 + } + } + ], + "span": { + "start": 2718, + "end": 2777 + } + }, + "span": { + "start": 2776, + "end": 2777 + } + } + ], + "comment": { + "content": [ + "Verify what shortcut for that operation", + "are recommended by the Human Interface Guidelines", + "of each platform for your locale." + ], + "span": { + "start": 2548, + "end": 2677 + } + }, + "span": { + "start": 2678, + "end": 2777 + } + }, + { + "type": "Message", + "id": { + "name": "bookmark-show-sidebar-shortcut", + "span": { + "start": 2907, + "end": 2937 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 2945, + "end": 2948 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "B", + "span": { + "start": 2951, + "end": 2953 + } + } + ], + "span": { + "start": 2951, + "end": 2954 + } + }, + "span": { + "start": 2953, + "end": 2954 + } + } + ], + "comment": { + "content": [ + "Verify what shortcut for that operation", + "are recommended by the Human Interface Guidelines", + "of each platform for your locale." + ], + "span": { + "start": 2777, + "end": 2906 + } + }, + "span": { + "start": 2907, + "end": 2954 + } + }, + { + "type": "GroupComment", + "content": [ + "All `-alt*` messages are alternative acceleration keys for zoom.", + "If shift key is needed with your locale popular keyboard for them,", + "you can use these alternative items. Otherwise, their values should be empty." + ], + "span": { + "start": 2954, + "end": 3172 + } + }, + { + "type": "Message", + "id": { + "name": "full-zoom-reduce-shortcut", + "span": { + "start": 3174, + "end": 3199 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3207, + "end": 3210 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "-", + "span": { + "start": 3213, + "end": 3215 + } + } + ], + "span": { + "start": 3213, + "end": 3216 + } + }, + "span": { + "start": 3215, + "end": 3216 + } + } + ], + "comment": null, + "span": { + "start": 3174, + "end": 3216 + } + }, + { + "type": "Message", + "id": { + "name": "full-zoom-reduce-shortcut-alt", + "span": { + "start": 3414, + "end": 3443 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3451, + "end": 3454 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "", + "span": { + "start": 3458, + "end": 3460 + } + }, + { + "start": 3458, + "end": 3460 + } + ], + "span": { + "start": 3457, + "end": 3460 + } + } + ], + "span": { + "start": 3457, + "end": 3463 + } + }, + "span": { + "start": 3462, + "end": 3463 + } + } + ], + "comment": { + "content": [ + "If in keyboard layouts popular for your locale you need to use the shift key", + "to access the original shortcuts, the following shortcuts can be used.", + "Otherwise their values should remain empty." + ], + "span": { + "start": 3216, + "end": 3413 + } + }, + "span": { + "start": 3414, + "end": 3463 + } + }, + { + "type": "Message", + "id": { + "name": "full-zoom-enlarge-shortcut", + "span": { + "start": 3463, + "end": 3489 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3497, + "end": 3500 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "+", + "span": { + "start": 3503, + "end": 3505 + } + } + ], + "span": { + "start": 3503, + "end": 3506 + } + }, + "span": { + "start": 3505, + "end": 3506 + } + } + ], + "comment": null, + "span": { + "start": 3463, + "end": 3506 + } + }, + { + "type": "Message", + "id": { + "name": "full-zoom-enlarge-shortcut-alt", + "span": { + "start": 3506, + "end": 3536 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3544, + "end": 3547 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "=", + "span": { + "start": 3550, + "end": 3552 + } + } + ], + "span": { + "start": 3550, + "end": 3553 + } + }, + "span": { + "start": 3552, + "end": 3553 + } + } + ], + "comment": null, + "span": { + "start": 3506, + "end": 3553 + } + }, + { + "type": "Message", + "id": { + "name": "full-zoom-enlarge-shortcut-alt2", + "span": { + "start": 3553, + "end": 3584 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3592, + "end": 3595 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "", + "span": { + "start": 3599, + "end": 3601 + } + }, + { + "start": 3599, + "end": 3601 + } + ], + "span": { + "start": 3598, + "end": 3601 + } + } + ], + "span": { + "start": 3598, + "end": 3604 + } + }, + "span": { + "start": 3603, + "end": 3604 + } + } + ], + "comment": null, + "span": { + "start": 3553, + "end": 3604 + } + }, + { + "type": "Message", + "id": { + "name": "full-zoom-reset-shortcut", + "span": { + "start": 3604, + "end": 3628 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3636, + "end": 3639 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "0", + "span": { + "start": 3642, + "end": 3644 + } + } + ], + "span": { + "start": 3642, + "end": 3645 + } + }, + "span": { + "start": 3644, + "end": 3645 + } + } + ], + "comment": null, + "span": { + "start": 3604, + "end": 3645 + } + }, + { + "type": "Message", + "id": { + "name": "full-zoom-reset-shortcut-alt", + "span": { + "start": 3645, + "end": 3673 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3681, + "end": 3684 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "StringLiteral", + "value": "", + "span": { + "start": 3688, + "end": 3690 + } + }, + { + "start": 3688, + "end": 3690 + } + ], + "span": { + "start": 3687, + "end": 3690 + } + } + ], + "span": { + "start": 3687, + "end": 3692 + } + }, + "span": { + "start": 3691, + "end": 3692 + } + } + ], + "comment": null, + "span": { + "start": 3645, + "end": 3692 + } + }, + { + "type": "GroupComment", + "content": [ + "" + ], + "span": { + "start": 3692, + "end": 3694 + } + }, + { + "type": "Message", + "id": { + "name": "bidi-switch-direction-shortcut", + "span": { + "start": 3696, + "end": 3726 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3734, + "end": 3737 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "X", + "span": { + "start": 3740, + "end": 3742 + } + } + ], + "span": { + "start": 3740, + "end": 3743 + } + }, + "span": { + "start": 3742, + "end": 3743 + } + } + ], + "comment": null, + "span": { + "start": 3696, + "end": 3743 + } + }, + { + "type": "Message", + "id": { + "name": "private-browsing-shortcut", + "span": { + "start": 3743, + "end": 3768 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3776, + "end": 3779 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "P", + "span": { + "start": 3782, + "end": 3784 + } + } + ], + "span": { + "start": 3782, + "end": 3785 + } + }, + "span": { + "start": 3784, + "end": 3785 + } + } + ], + "comment": null, + "span": { + "start": 3743, + "end": 3785 + } + }, + { + "type": "GroupComment", + "content": [ + "The shortcuts below are for Mac specific", + "global menu." + ], + "span": { + "start": 3785, + "end": 3844 + } + }, + { + "type": "Message", + "id": { + "name": "quit-app-shortcut", + "span": { + "start": 3846, + "end": 3863 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3871, + "end": 3874 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Q", + "span": { + "start": 3877, + "end": 3879 + } + } + ], + "span": { + "start": 3877, + "end": 3880 + } + }, + "span": { + "start": 3879, + "end": 3880 + } + } + ], + "comment": null, + "span": { + "start": 3846, + "end": 3880 + } + }, + { + "type": "Message", + "id": { + "name": "help-shortcut", + "span": { + "start": 3880, + "end": 3893 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3901, + "end": 3904 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "?", + "span": { + "start": 3907, + "end": 3909 + } + } + ], + "span": { + "start": 3907, + "end": 3910 + } + }, + "span": { + "start": 3909, + "end": 3910 + } + } + ], + "comment": null, + "span": { + "start": 3880, + "end": 3910 + } + }, + { + "type": "Message", + "id": { + "name": "preferences-shortcut", + "span": { + "start": 3910, + "end": 3930 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3938, + "end": 3941 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": ",", + "span": { + "start": 3944, + "end": 3946 + } + } + ], + "span": { + "start": 3944, + "end": 3947 + } + }, + "span": { + "start": 3946, + "end": 3947 + } + } + ], + "comment": null, + "span": { + "start": 3910, + "end": 3947 + } + }, + { + "type": "Message", + "id": { + "name": "hide-app-shortcut", + "span": { + "start": 3947, + "end": 3964 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 3972, + "end": 3975 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "H", + "span": { + "start": 3978, + "end": 3980 + } + } + ], + "span": { + "start": 3978, + "end": 3981 + } + }, + "span": { + "start": 3980, + "end": 3981 + } + } + ], + "comment": null, + "span": { + "start": 3947, + "end": 3981 + } + }, + { + "type": "Message", + "id": { + "name": "hide-other-apps-shortcut", + "span": { + "start": 3981, + "end": 4005 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 4013, + "end": 4016 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "H", + "span": { + "start": 4019, + "end": 4021 + } + } + ], + "span": { + "start": 4019, + "end": 4021 + } + }, + "span": { + "start": 4020, + "end": 4021 + } + } + ], + "comment": null, + "span": { + "start": 3981, + "end": 4021 + } + } + ], + "span": { + "start": 0, + "end": 4021 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/interventions.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/interventions.spans.json new file mode 100644 index 00000000..3638ae54 --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/interventions.spans.json @@ -0,0 +1,692 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "ResourceComment", + "content": [ + "These strings appear in Urlbar Interventions. Interventions appear in the", + "Urlbar in response to the user's query. For example, if we detect that the", + "user is searching how to clear their history, we show the Intervention", + "described by clear-data." + ], + "span": { + "start": 200, + "end": 460 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-clear-data", + "span": { + "start": 462, + "end": 485 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Clear your cache, cookies, history and more.", + "span": { + "start": 488, + "end": 533 + } + } + ], + "span": { + "start": 488, + "end": 533 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 462, + "end": 533 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-clear-data-confirm", + "span": { + "start": 533, + "end": 564 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Choose What to Clear…", + "span": { + "start": 567, + "end": 591 + } + } + ], + "span": { + "start": 567, + "end": 591 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 533, + "end": 591 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-refresh-profile", + "span": { + "start": 591, + "end": 619 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Restore default settings and remove old add-ons for optimal performance.", + "span": { + "start": 622, + "end": 695 + } + } + ], + "span": { + "start": 622, + "end": 695 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 591, + "end": 695 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-refresh-profile-confirm", + "span": { + "start": 695, + "end": 731 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Refresh ", + "span": { + "start": 734, + "end": 742 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-short-name", + "span": { + "start": 745, + "end": 761 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 744, + "end": 762 + } + }, + { + "start": 744, + "end": 762 + } + ], + "span": { + "start": 742, + "end": 762 + } + }, + { + "type": "TextElement", + "value": "…", + "span": { + "start": 763, + "end": 767 + } + } + ], + "span": { + "start": 734, + "end": 768 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 695, + "end": 768 + } + }, + { + "type": "GroupComment", + "content": [ + "These strings describe Interventions helping the user with the Firefox update", + "process." + ], + "span": { + "start": 768, + "end": 860 + } + }, + { + "type": "GroupComment", + "content": [ + "Shown when an update is available to download." + ], + "span": { + "start": 862, + "end": 911 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-update-ask", + "span": { + "start": 913, + "end": 936 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A new version of ", + "span": { + "start": 939, + "end": 956 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-short-name", + "span": { + "start": 959, + "end": 975 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 958, + "end": 976 + } + }, + { + "start": 958, + "end": 976 + } + ], + "span": { + "start": 956, + "end": 976 + } + }, + { + "type": "TextElement", + "value": " is available.", + "span": { + "start": 977, + "end": 992 + } + } + ], + "span": { + "start": 939, + "end": 992 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 913, + "end": 992 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-update-ask-confirm", + "span": { + "start": 992, + "end": 1023 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Install and Restart to Update", + "span": { + "start": 1026, + "end": 1056 + } + } + ], + "span": { + "start": 1026, + "end": 1057 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 992, + "end": 1057 + } + }, + { + "type": "GroupComment", + "content": [ + "Shown when Firefox does not need to update so instead we offer to refresh", + "the user's profile." + ], + "span": { + "start": 1057, + "end": 1156 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-update-refresh", + "span": { + "start": 1158, + "end": 1185 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-short-name", + "span": { + "start": 1191, + "end": 1207 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 1190, + "end": 1208 + } + }, + { + "start": 1190, + "end": 1208 + } + ], + "span": { + "start": 1188, + "end": 1208 + } + }, + { + "type": "TextElement", + "value": " is up to date. Trying to fix a problem? Restore default settings and remove old add-ons for optimal performance.", + "span": { + "start": 1209, + "end": 1323 + } + } + ], + "span": { + "start": 1188, + "end": 1323 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1158, + "end": 1323 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-update-refresh-confirm", + "span": { + "start": 1323, + "end": 1358 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Refresh ", + "span": { + "start": 1361, + "end": 1369 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-short-name", + "span": { + "start": 1372, + "end": 1388 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 1371, + "end": 1389 + } + }, + { + "start": 1371, + "end": 1389 + } + ], + "span": { + "start": 1369, + "end": 1389 + } + }, + { + "type": "TextElement", + "value": "…", + "span": { + "start": 1390, + "end": 1394 + } + } + ], + "span": { + "start": 1361, + "end": 1395 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1323, + "end": 1395 + } + }, + { + "type": "GroupComment", + "content": [ + "Shown when an update is downloaded and Firefox is ready to install it." + ], + "span": { + "start": 1395, + "end": 1468 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-update-restart", + "span": { + "start": 1470, + "end": 1497 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "The latest ", + "span": { + "start": 1500, + "end": 1511 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-short-name", + "span": { + "start": 1514, + "end": 1530 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 1513, + "end": 1531 + } + }, + { + "start": 1513, + "end": 1531 + } + ], + "span": { + "start": 1511, + "end": 1531 + } + }, + { + "type": "TextElement", + "value": " is downloaded and ready to install.", + "span": { + "start": 1532, + "end": 1569 + } + } + ], + "span": { + "start": 1500, + "end": 1569 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1470, + "end": 1569 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-update-restart-confirm", + "span": { + "start": 1569, + "end": 1604 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Restart to Update", + "span": { + "start": 1607, + "end": 1625 + } + } + ], + "span": { + "start": 1607, + "end": 1626 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1569, + "end": 1626 + } + }, + { + "type": "GroupComment", + "content": [ + "Shown when Firefox cannot update itself. The button will open the download", + "page on the Firefox website." + ], + "span": { + "start": 1626, + "end": 1735 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-update-web", + "span": { + "start": 1737, + "end": 1760 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Get the latest ", + "span": { + "start": 1763, + "end": 1778 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-short-name", + "span": { + "start": 1781, + "end": 1797 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 1780, + "end": 1798 + } + }, + { + "start": 1780, + "end": 1798 + } + ], + "span": { + "start": 1778, + "end": 1798 + } + }, + { + "type": "TextElement", + "value": " browser.", + "span": { + "start": 1799, + "end": 1809 + } + } + ], + "span": { + "start": 1763, + "end": 1809 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1737, + "end": 1809 + } + }, + { + "type": "Message", + "id": { + "name": "intervention-update-web-confirm", + "span": { + "start": 1809, + "end": 1840 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Download Now", + "span": { + "start": 1843, + "end": 1856 + } + } + ], + "span": { + "start": 1843, + "end": 1857 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 1809, + "end": 1857 + } + }, + { + "type": "GroupComment", + "content": [], + "span": { + "start": 1857, + "end": 1859 + } + } + ], + "span": { + "start": 0, + "end": 1859 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/menubar.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/menubar.spans.json new file mode 100644 index 00000000..be6ef376 --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/menubar.spans.json @@ -0,0 +1,6073 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "GroupComment", + "content": [ + "File Menu" + ], + "span": { + "start": 200, + "end": 212 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file", + "span": { + "start": 214, + "end": 223 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 231, + "end": 236 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "File", + "span": { + "start": 239, + "end": 244 + } + } + ], + "span": { + "start": 239, + "end": 244 + } + }, + "span": { + "start": 243, + "end": 244 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 249, + "end": 258 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 261, + "end": 263 + } + } + ], + "span": { + "start": 261, + "end": 263 + } + }, + "span": { + "start": 262, + "end": 263 + } + } + ], + "comment": null, + "span": { + "start": 214, + "end": 263 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-new-tab", + "span": { + "start": 263, + "end": 280 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 288, + "end": 293 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "New Tab", + "span": { + "start": 296, + "end": 304 + } + } + ], + "span": { + "start": 296, + "end": 304 + } + }, + "span": { + "start": 303, + "end": 304 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 309, + "end": 318 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "T", + "span": { + "start": 321, + "end": 323 + } + } + ], + "span": { + "start": 321, + "end": 323 + } + }, + "span": { + "start": 322, + "end": 323 + } + } + ], + "comment": null, + "span": { + "start": 263, + "end": 323 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-new-container-tab", + "span": { + "start": 323, + "end": 350 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 358, + "end": 363 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "New Container Tab", + "span": { + "start": 366, + "end": 384 + } + } + ], + "span": { + "start": 366, + "end": 384 + } + }, + "span": { + "start": 383, + "end": 384 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 389, + "end": 398 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "b", + "span": { + "start": 401, + "end": 403 + } + } + ], + "span": { + "start": 401, + "end": 403 + } + }, + "span": { + "start": 402, + "end": 403 + } + } + ], + "comment": null, + "span": { + "start": 323, + "end": 403 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-new-window", + "span": { + "start": 403, + "end": 423 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 431, + "end": 436 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "New Window", + "span": { + "start": 439, + "end": 450 + } + } + ], + "span": { + "start": 439, + "end": 450 + } + }, + "span": { + "start": 449, + "end": 450 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 455, + "end": 464 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "N", + "span": { + "start": 467, + "end": 469 + } + } + ], + "span": { + "start": 467, + "end": 469 + } + }, + "span": { + "start": 468, + "end": 469 + } + } + ], + "comment": null, + "span": { + "start": 403, + "end": 469 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-new-private-window", + "span": { + "start": 469, + "end": 497 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 505, + "end": 510 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "New Private Window", + "span": { + "start": 513, + "end": 532 + } + } + ], + "span": { + "start": 513, + "end": 532 + } + }, + "span": { + "start": 531, + "end": 532 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 537, + "end": 546 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "W", + "span": { + "start": 549, + "end": 551 + } + } + ], + "span": { + "start": 549, + "end": 551 + } + }, + "span": { + "start": 550, + "end": 551 + } + } + ], + "comment": null, + "span": { + "start": 469, + "end": 551 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-open-location", + "span": { + "start": 714, + "end": 737 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 745, + "end": 750 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open Location…", + "span": { + "start": 753, + "end": 770 + } + } + ], + "span": { + "start": 753, + "end": 770 + } + }, + "span": { + "start": 769, + "end": 770 + } + } + ], + "comment": { + "content": [ + "\"Open Location\" is only displayed on macOS, and only on windows", + "that aren't main browser windows, or when there are no windows", + "but Firefox is still running." + ], + "span": { + "start": 551, + "end": 713 + } + }, + "span": { + "start": 714, + "end": 770 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-open-file", + "span": { + "start": 770, + "end": 789 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 797, + "end": 802 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Open File…", + "span": { + "start": 805, + "end": 818 + } + } + ], + "span": { + "start": 805, + "end": 818 + } + }, + "span": { + "start": 817, + "end": 818 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 823, + "end": 832 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "O", + "span": { + "start": 835, + "end": 837 + } + } + ], + "span": { + "start": 835, + "end": 837 + } + }, + "span": { + "start": 836, + "end": 837 + } + } + ], + "comment": null, + "span": { + "start": 770, + "end": 837 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-close", + "span": { + "start": 837, + "end": 852 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 860, + "end": 865 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Close", + "span": { + "start": 868, + "end": 874 + } + } + ], + "span": { + "start": 868, + "end": 874 + } + }, + "span": { + "start": 873, + "end": 874 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 879, + "end": 888 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "C", + "span": { + "start": 891, + "end": 893 + } + } + ], + "span": { + "start": 891, + "end": 893 + } + }, + "span": { + "start": 892, + "end": 893 + } + } + ], + "comment": null, + "span": { + "start": 837, + "end": 893 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-close-window", + "span": { + "start": 893, + "end": 915 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 923, + "end": 928 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Close Window", + "span": { + "start": 931, + "end": 944 + } + } + ], + "span": { + "start": 931, + "end": 944 + } + }, + "span": { + "start": 943, + "end": 944 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 949, + "end": 958 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "d", + "span": { + "start": 961, + "end": 963 + } + } + ], + "span": { + "start": 961, + "end": 963 + } + }, + "span": { + "start": 962, + "end": 963 + } + } + ], + "comment": null, + "span": { + "start": 893, + "end": 963 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-save-page", + "span": { + "start": 963, + "end": 982 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 990, + "end": 995 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Save Page As…", + "span": { + "start": 998, + "end": 1014 + } + } + ], + "span": { + "start": 998, + "end": 1014 + } + }, + "span": { + "start": 1013, + "end": 1014 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1019, + "end": 1028 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A", + "span": { + "start": 1031, + "end": 1033 + } + } + ], + "span": { + "start": 1031, + "end": 1033 + } + }, + "span": { + "start": 1032, + "end": 1033 + } + } + ], + "comment": null, + "span": { + "start": 963, + "end": 1033 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-email-link", + "span": { + "start": 1033, + "end": 1053 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1061, + "end": 1066 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Email Link…", + "span": { + "start": 1069, + "end": 1083 + } + } + ], + "span": { + "start": 1069, + "end": 1083 + } + }, + "span": { + "start": 1082, + "end": 1083 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1088, + "end": 1097 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "E", + "span": { + "start": 1100, + "end": 1102 + } + } + ], + "span": { + "start": 1100, + "end": 1102 + } + }, + "span": { + "start": 1101, + "end": 1102 + } + } + ], + "comment": null, + "span": { + "start": 1033, + "end": 1102 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-print-setup", + "span": { + "start": 1102, + "end": 1123 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1131, + "end": 1136 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Page Setup…", + "span": { + "start": 1139, + "end": 1153 + } + } + ], + "span": { + "start": 1139, + "end": 1153 + } + }, + "span": { + "start": 1152, + "end": 1153 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1158, + "end": 1167 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "u", + "span": { + "start": 1170, + "end": 1172 + } + } + ], + "span": { + "start": 1170, + "end": 1172 + } + }, + "span": { + "start": 1171, + "end": 1172 + } + } + ], + "comment": null, + "span": { + "start": 1102, + "end": 1172 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-print-preview", + "span": { + "start": 1172, + "end": 1195 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1203, + "end": 1208 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Print Preview", + "span": { + "start": 1211, + "end": 1225 + } + } + ], + "span": { + "start": 1211, + "end": 1225 + } + }, + "span": { + "start": 1224, + "end": 1225 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1230, + "end": 1239 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "v", + "span": { + "start": 1242, + "end": 1244 + } + } + ], + "span": { + "start": 1242, + "end": 1244 + } + }, + "span": { + "start": 1243, + "end": 1244 + } + } + ], + "comment": null, + "span": { + "start": 1172, + "end": 1244 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-print", + "span": { + "start": 1244, + "end": 1259 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1267, + "end": 1272 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Print…", + "span": { + "start": 1275, + "end": 1284 + } + } + ], + "span": { + "start": 1275, + "end": 1284 + } + }, + "span": { + "start": 1283, + "end": 1284 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1289, + "end": 1298 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "P", + "span": { + "start": 1301, + "end": 1303 + } + } + ], + "span": { + "start": 1301, + "end": 1303 + } + }, + "span": { + "start": 1302, + "end": 1303 + } + } + ], + "comment": null, + "span": { + "start": 1244, + "end": 1303 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-import-from-another-browser", + "span": { + "start": 1303, + "end": 1340 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1348, + "end": 1353 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Import from Another Browser…", + "span": { + "start": 1356, + "end": 1387 + } + } + ], + "span": { + "start": 1356, + "end": 1387 + } + }, + "span": { + "start": 1386, + "end": 1387 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1392, + "end": 1401 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "I", + "span": { + "start": 1404, + "end": 1406 + } + } + ], + "span": { + "start": 1404, + "end": 1406 + } + }, + "span": { + "start": 1405, + "end": 1406 + } + } + ], + "comment": null, + "span": { + "start": 1303, + "end": 1406 + } + }, + { + "type": "Message", + "id": { + "name": "menu-file-go-offline", + "span": { + "start": 1406, + "end": 1426 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1434, + "end": 1439 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Work Offline", + "span": { + "start": 1442, + "end": 1455 + } + } + ], + "span": { + "start": 1442, + "end": 1455 + } + }, + "span": { + "start": 1454, + "end": 1455 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1460, + "end": 1469 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "k", + "span": { + "start": 1472, + "end": 1474 + } + } + ], + "span": { + "start": 1472, + "end": 1475 + } + }, + "span": { + "start": 1474, + "end": 1475 + } + } + ], + "comment": null, + "span": { + "start": 1406, + "end": 1475 + } + }, + { + "type": "GroupComment", + "content": [ + "Edit Menu" + ], + "span": { + "start": 1475, + "end": 1487 + } + }, + { + "type": "Message", + "id": { + "name": "menu-edit", + "span": { + "start": 1489, + "end": 1498 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1506, + "end": 1511 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Edit", + "span": { + "start": 1514, + "end": 1519 + } + } + ], + "span": { + "start": 1514, + "end": 1519 + } + }, + "span": { + "start": 1518, + "end": 1519 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1524, + "end": 1533 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "E", + "span": { + "start": 1536, + "end": 1538 + } + } + ], + "span": { + "start": 1536, + "end": 1538 + } + }, + "span": { + "start": 1537, + "end": 1538 + } + } + ], + "comment": null, + "span": { + "start": 1489, + "end": 1538 + } + }, + { + "type": "Message", + "id": { + "name": "menu-edit-find-on", + "span": { + "start": 1538, + "end": 1555 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1563, + "end": 1568 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Find in This Page…", + "span": { + "start": 1571, + "end": 1592 + } + } + ], + "span": { + "start": 1571, + "end": 1592 + } + }, + "span": { + "start": 1591, + "end": 1592 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1597, + "end": 1606 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 1609, + "end": 1611 + } + } + ], + "span": { + "start": 1609, + "end": 1611 + } + }, + "span": { + "start": 1610, + "end": 1611 + } + } + ], + "comment": null, + "span": { + "start": 1538, + "end": 1611 + } + }, + { + "type": "Message", + "id": { + "name": "menu-edit-find-again", + "span": { + "start": 1611, + "end": 1631 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1639, + "end": 1644 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Find Again", + "span": { + "start": 1647, + "end": 1658 + } + } + ], + "span": { + "start": 1647, + "end": 1658 + } + }, + "span": { + "start": 1657, + "end": 1658 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1663, + "end": 1672 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "g", + "span": { + "start": 1675, + "end": 1677 + } + } + ], + "span": { + "start": 1675, + "end": 1677 + } + }, + "span": { + "start": 1676, + "end": 1677 + } + } + ], + "comment": null, + "span": { + "start": 1611, + "end": 1677 + } + }, + { + "type": "Message", + "id": { + "name": "menu-edit-bidi-switch-text-direction", + "span": { + "start": 1677, + "end": 1713 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1721, + "end": 1726 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Switch Text Direction", + "span": { + "start": 1729, + "end": 1751 + } + } + ], + "span": { + "start": 1729, + "end": 1751 + } + }, + "span": { + "start": 1750, + "end": 1751 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1756, + "end": 1765 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "w", + "span": { + "start": 1768, + "end": 1770 + } + } + ], + "span": { + "start": 1768, + "end": 1771 + } + }, + "span": { + "start": 1770, + "end": 1771 + } + } + ], + "comment": null, + "span": { + "start": 1677, + "end": 1771 + } + }, + { + "type": "GroupComment", + "content": [ + "View Menu" + ], + "span": { + "start": 1771, + "end": 1783 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view", + "span": { + "start": 1785, + "end": 1794 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1802, + "end": 1807 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "View", + "span": { + "start": 1810, + "end": 1815 + } + } + ], + "span": { + "start": 1810, + "end": 1815 + } + }, + "span": { + "start": 1814, + "end": 1815 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1820, + "end": 1829 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "V", + "span": { + "start": 1832, + "end": 1834 + } + } + ], + "span": { + "start": 1832, + "end": 1834 + } + }, + "span": { + "start": 1833, + "end": 1834 + } + } + ], + "comment": null, + "span": { + "start": 1785, + "end": 1834 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-toolbars-menu", + "span": { + "start": 1834, + "end": 1857 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1865, + "end": 1870 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Toolbars", + "span": { + "start": 1873, + "end": 1882 + } + } + ], + "span": { + "start": 1873, + "end": 1882 + } + }, + "span": { + "start": 1881, + "end": 1882 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1887, + "end": 1896 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "T", + "span": { + "start": 1899, + "end": 1901 + } + } + ], + "span": { + "start": 1899, + "end": 1901 + } + }, + "span": { + "start": 1900, + "end": 1901 + } + } + ], + "comment": null, + "span": { + "start": 1834, + "end": 1901 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-customize-toolbar", + "span": { + "start": 1901, + "end": 1928 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 1936, + "end": 1941 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Customize…", + "span": { + "start": 1944, + "end": 1957 + } + } + ], + "span": { + "start": 1944, + "end": 1957 + } + }, + "span": { + "start": 1956, + "end": 1957 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 1962, + "end": 1971 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "C", + "span": { + "start": 1974, + "end": 1976 + } + } + ], + "span": { + "start": 1974, + "end": 1976 + } + }, + "span": { + "start": 1975, + "end": 1976 + } + } + ], + "comment": null, + "span": { + "start": 1901, + "end": 1976 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-sidebar", + "span": { + "start": 1976, + "end": 1993 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2001, + "end": 2006 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Sidebar", + "span": { + "start": 2009, + "end": 2017 + } + } + ], + "span": { + "start": 2009, + "end": 2017 + } + }, + "span": { + "start": 2016, + "end": 2017 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2022, + "end": 2031 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "e", + "span": { + "start": 2034, + "end": 2036 + } + } + ], + "span": { + "start": 2034, + "end": 2036 + } + }, + "span": { + "start": 2035, + "end": 2036 + } + } + ], + "comment": null, + "span": { + "start": 1976, + "end": 2036 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-bookmarks", + "span": { + "start": 2036, + "end": 2055 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2063, + "end": 2068 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmarks", + "span": { + "start": 2071, + "end": 2081 + } + } + ], + "span": { + "start": 2071, + "end": 2081 + } + }, + "span": { + "start": 2080, + "end": 2081 + } + } + ], + "comment": null, + "span": { + "start": 2036, + "end": 2081 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-history-button", + "span": { + "start": 2081, + "end": 2105 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2113, + "end": 2118 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "History", + "span": { + "start": 2121, + "end": 2129 + } + } + ], + "span": { + "start": 2121, + "end": 2129 + } + }, + "span": { + "start": 2128, + "end": 2129 + } + } + ], + "comment": null, + "span": { + "start": 2081, + "end": 2129 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-synced-tabs-sidebar", + "span": { + "start": 2129, + "end": 2158 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2166, + "end": 2171 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Synced Tabs", + "span": { + "start": 2174, + "end": 2186 + } + } + ], + "span": { + "start": 2174, + "end": 2186 + } + }, + "span": { + "start": 2185, + "end": 2186 + } + } + ], + "comment": null, + "span": { + "start": 2129, + "end": 2186 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-full-zoom", + "span": { + "start": 2186, + "end": 2205 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2213, + "end": 2218 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Zoom", + "span": { + "start": 2221, + "end": 2226 + } + } + ], + "span": { + "start": 2221, + "end": 2226 + } + }, + "span": { + "start": 2225, + "end": 2226 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2231, + "end": 2240 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Z", + "span": { + "start": 2243, + "end": 2245 + } + } + ], + "span": { + "start": 2243, + "end": 2245 + } + }, + "span": { + "start": 2244, + "end": 2245 + } + } + ], + "comment": null, + "span": { + "start": 2186, + "end": 2245 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-full-zoom-enlarge", + "span": { + "start": 2245, + "end": 2272 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2280, + "end": 2285 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Zoom In", + "span": { + "start": 2288, + "end": 2296 + } + } + ], + "span": { + "start": 2288, + "end": 2296 + } + }, + "span": { + "start": 2295, + "end": 2296 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2301, + "end": 2310 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "I", + "span": { + "start": 2313, + "end": 2315 + } + } + ], + "span": { + "start": 2313, + "end": 2315 + } + }, + "span": { + "start": 2314, + "end": 2315 + } + } + ], + "comment": null, + "span": { + "start": 2245, + "end": 2315 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-full-zoom-reduce", + "span": { + "start": 2315, + "end": 2341 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2349, + "end": 2354 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Zoom Out", + "span": { + "start": 2357, + "end": 2366 + } + } + ], + "span": { + "start": 2357, + "end": 2366 + } + }, + "span": { + "start": 2365, + "end": 2366 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2371, + "end": 2380 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "O", + "span": { + "start": 2383, + "end": 2385 + } + } + ], + "span": { + "start": 2383, + "end": 2385 + } + }, + "span": { + "start": 2384, + "end": 2385 + } + } + ], + "comment": null, + "span": { + "start": 2315, + "end": 2385 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-full-zoom-actual-size", + "span": { + "start": 2385, + "end": 2416 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2424, + "end": 2429 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Actual Size", + "span": { + "start": 2432, + "end": 2444 + } + } + ], + "span": { + "start": 2432, + "end": 2444 + } + }, + "span": { + "start": 2443, + "end": 2444 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2449, + "end": 2458 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A", + "span": { + "start": 2461, + "end": 2463 + } + } + ], + "span": { + "start": 2461, + "end": 2463 + } + }, + "span": { + "start": 2462, + "end": 2463 + } + } + ], + "comment": null, + "span": { + "start": 2385, + "end": 2463 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-full-zoom-toggle", + "span": { + "start": 2463, + "end": 2489 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2497, + "end": 2502 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Zoom Text Only", + "span": { + "start": 2505, + "end": 2520 + } + } + ], + "span": { + "start": 2505, + "end": 2520 + } + }, + "span": { + "start": 2519, + "end": 2520 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2525, + "end": 2534 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "T", + "span": { + "start": 2537, + "end": 2539 + } + } + ], + "span": { + "start": 2537, + "end": 2539 + } + }, + "span": { + "start": 2538, + "end": 2539 + } + } + ], + "comment": null, + "span": { + "start": 2463, + "end": 2539 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-page-style-menu", + "span": { + "start": 2539, + "end": 2564 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2572, + "end": 2577 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Page Style", + "span": { + "start": 2580, + "end": 2591 + } + } + ], + "span": { + "start": 2580, + "end": 2591 + } + }, + "span": { + "start": 2590, + "end": 2591 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2596, + "end": 2605 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "y", + "span": { + "start": 2608, + "end": 2610 + } + } + ], + "span": { + "start": 2608, + "end": 2610 + } + }, + "span": { + "start": 2609, + "end": 2610 + } + } + ], + "comment": null, + "span": { + "start": 2539, + "end": 2610 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-page-style-no-style", + "span": { + "start": 2610, + "end": 2639 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2647, + "end": 2652 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "No Style", + "span": { + "start": 2655, + "end": 2664 + } + } + ], + "span": { + "start": 2655, + "end": 2664 + } + }, + "span": { + "start": 2663, + "end": 2664 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2669, + "end": 2678 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "n", + "span": { + "start": 2681, + "end": 2683 + } + } + ], + "span": { + "start": 2681, + "end": 2683 + } + }, + "span": { + "start": 2682, + "end": 2683 + } + } + ], + "comment": null, + "span": { + "start": 2610, + "end": 2683 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-page-basic-style", + "span": { + "start": 2683, + "end": 2709 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2717, + "end": 2722 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Basic Page Style", + "span": { + "start": 2725, + "end": 2742 + } + } + ], + "span": { + "start": 2725, + "end": 2742 + } + }, + "span": { + "start": 2741, + "end": 2742 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2747, + "end": 2756 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "B", + "span": { + "start": 2759, + "end": 2761 + } + } + ], + "span": { + "start": 2759, + "end": 2761 + } + }, + "span": { + "start": 2760, + "end": 2761 + } + } + ], + "comment": null, + "span": { + "start": 2683, + "end": 2761 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-charset", + "span": { + "start": 2761, + "end": 2778 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2786, + "end": 2791 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Text Encoding", + "span": { + "start": 2794, + "end": 2808 + } + } + ], + "span": { + "start": 2794, + "end": 2808 + } + }, + "span": { + "start": 2807, + "end": 2808 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2813, + "end": 2822 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "c", + "span": { + "start": 2825, + "end": 2827 + } + } + ], + "span": { + "start": 2825, + "end": 2828 + } + }, + "span": { + "start": 2827, + "end": 2828 + } + } + ], + "comment": null, + "span": { + "start": 2761, + "end": 2828 + } + }, + { + "type": "GroupComment", + "content": [ + "These should match what Safari and other Apple applications", + "use on macOS." + ], + "span": { + "start": 2828, + "end": 2907 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-enter-full-screen", + "span": { + "start": 2909, + "end": 2936 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 2944, + "end": 2949 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Enter Full Screen", + "span": { + "start": 2952, + "end": 2970 + } + } + ], + "span": { + "start": 2952, + "end": 2970 + } + }, + "span": { + "start": 2969, + "end": 2970 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 2975, + "end": 2984 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 2987, + "end": 2989 + } + } + ], + "span": { + "start": 2987, + "end": 2989 + } + }, + "span": { + "start": 2988, + "end": 2989 + } + } + ], + "comment": null, + "span": { + "start": 2909, + "end": 2989 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-exit-full-screen", + "span": { + "start": 2989, + "end": 3015 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3023, + "end": 3028 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Exit Full Screen", + "span": { + "start": 3031, + "end": 3048 + } + } + ], + "span": { + "start": 3031, + "end": 3048 + } + }, + "span": { + "start": 3047, + "end": 3048 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3053, + "end": 3062 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 3065, + "end": 3067 + } + } + ], + "span": { + "start": 3065, + "end": 3067 + } + }, + "span": { + "start": 3066, + "end": 3067 + } + } + ], + "comment": null, + "span": { + "start": 2989, + "end": 3067 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-full-screen", + "span": { + "start": 3067, + "end": 3088 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3096, + "end": 3101 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Full Screen", + "span": { + "start": 3104, + "end": 3116 + } + } + ], + "span": { + "start": 3104, + "end": 3116 + } + }, + "span": { + "start": 3115, + "end": 3116 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3121, + "end": 3130 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "F", + "span": { + "start": 3133, + "end": 3135 + } + } + ], + "span": { + "start": 3133, + "end": 3136 + } + }, + "span": { + "start": 3135, + "end": 3136 + } + } + ], + "comment": null, + "span": { + "start": 3067, + "end": 3136 + } + }, + { + "type": "GroupComment", + "content": [ + "" + ], + "span": { + "start": 3136, + "end": 3138 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-show-all-tabs", + "span": { + "start": 3140, + "end": 3163 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3171, + "end": 3176 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Show All Tabs", + "span": { + "start": 3179, + "end": 3193 + } + } + ], + "span": { + "start": 3179, + "end": 3193 + } + }, + "span": { + "start": 3192, + "end": 3193 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3198, + "end": 3207 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A", + "span": { + "start": 3210, + "end": 3212 + } + } + ], + "span": { + "start": 3210, + "end": 3212 + } + }, + "span": { + "start": 3211, + "end": 3212 + } + } + ], + "comment": null, + "span": { + "start": 3140, + "end": 3212 + } + }, + { + "type": "Message", + "id": { + "name": "menu-view-bidi-switch-page-direction", + "span": { + "start": 3212, + "end": 3248 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3256, + "end": 3261 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Switch Page Direction", + "span": { + "start": 3264, + "end": 3286 + } + } + ], + "span": { + "start": 3264, + "end": 3286 + } + }, + "span": { + "start": 3285, + "end": 3286 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3291, + "end": 3300 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 3303, + "end": 3305 + } + } + ], + "span": { + "start": 3303, + "end": 3306 + } + }, + "span": { + "start": 3305, + "end": 3306 + } + } + ], + "comment": null, + "span": { + "start": 3212, + "end": 3306 + } + }, + { + "type": "GroupComment", + "content": [ + "History Menu" + ], + "span": { + "start": 3306, + "end": 3321 + } + }, + { + "type": "Message", + "id": { + "name": "menu-history", + "span": { + "start": 3323, + "end": 3335 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3343, + "end": 3348 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "History", + "span": { + "start": 3351, + "end": 3359 + } + } + ], + "span": { + "start": 3351, + "end": 3359 + } + }, + "span": { + "start": 3358, + "end": 3359 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3364, + "end": 3373 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "s", + "span": { + "start": 3376, + "end": 3378 + } + } + ], + "span": { + "start": 3376, + "end": 3378 + } + }, + "span": { + "start": 3377, + "end": 3378 + } + } + ], + "comment": null, + "span": { + "start": 3323, + "end": 3378 + } + }, + { + "type": "Message", + "id": { + "name": "menu-history-show-all-history", + "span": { + "start": 3378, + "end": 3407 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3415, + "end": 3420 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Show All History", + "span": { + "start": 3423, + "end": 3440 + } + } + ], + "span": { + "start": 3423, + "end": 3440 + } + }, + "span": { + "start": 3439, + "end": 3440 + } + } + ], + "comment": null, + "span": { + "start": 3378, + "end": 3440 + } + }, + { + "type": "Message", + "id": { + "name": "menu-history-clear-recent-history", + "span": { + "start": 3440, + "end": 3473 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3481, + "end": 3486 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Clear Recent History…", + "span": { + "start": 3489, + "end": 3513 + } + } + ], + "span": { + "start": 3489, + "end": 3513 + } + }, + "span": { + "start": 3512, + "end": 3513 + } + } + ], + "comment": null, + "span": { + "start": 3440, + "end": 3513 + } + }, + { + "type": "Message", + "id": { + "name": "menu-history-synced-tabs", + "span": { + "start": 3513, + "end": 3537 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3545, + "end": 3550 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Synced Tabs", + "span": { + "start": 3553, + "end": 3565 + } + } + ], + "span": { + "start": 3553, + "end": 3565 + } + }, + "span": { + "start": 3564, + "end": 3565 + } + } + ], + "comment": null, + "span": { + "start": 3513, + "end": 3565 + } + }, + { + "type": "Message", + "id": { + "name": "menu-history-restore-last-session", + "span": { + "start": 3565, + "end": 3598 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3606, + "end": 3611 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Restore Previous Session", + "span": { + "start": 3614, + "end": 3639 + } + } + ], + "span": { + "start": 3614, + "end": 3639 + } + }, + "span": { + "start": 3638, + "end": 3639 + } + } + ], + "comment": null, + "span": { + "start": 3565, + "end": 3639 + } + }, + { + "type": "Message", + "id": { + "name": "menu-history-hidden-tabs", + "span": { + "start": 3639, + "end": 3663 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3671, + "end": 3676 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Hidden Tabs", + "span": { + "start": 3679, + "end": 3691 + } + } + ], + "span": { + "start": 3679, + "end": 3691 + } + }, + "span": { + "start": 3690, + "end": 3691 + } + } + ], + "comment": null, + "span": { + "start": 3639, + "end": 3691 + } + }, + { + "type": "Message", + "id": { + "name": "menu-history-undo-menu", + "span": { + "start": 3691, + "end": 3713 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3721, + "end": 3726 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Recently Closed Tabs", + "span": { + "start": 3729, + "end": 3750 + } + } + ], + "span": { + "start": 3729, + "end": 3750 + } + }, + "span": { + "start": 3749, + "end": 3750 + } + } + ], + "comment": null, + "span": { + "start": 3691, + "end": 3750 + } + }, + { + "type": "Message", + "id": { + "name": "menu-history-undo-window-menu", + "span": { + "start": 3750, + "end": 3779 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3787, + "end": 3792 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Recently Closed Windows", + "span": { + "start": 3795, + "end": 3819 + } + } + ], + "span": { + "start": 3795, + "end": 3820 + } + }, + "span": { + "start": 3819, + "end": 3820 + } + } + ], + "comment": null, + "span": { + "start": 3750, + "end": 3820 + } + }, + { + "type": "GroupComment", + "content": [ + "Bookmarks Menu" + ], + "span": { + "start": 3820, + "end": 3837 + } + }, + { + "type": "Message", + "id": { + "name": "menu-bookmarks-menu", + "span": { + "start": 3839, + "end": 3858 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3866, + "end": 3871 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmarks", + "span": { + "start": 3874, + "end": 3884 + } + } + ], + "span": { + "start": 3874, + "end": 3884 + } + }, + "span": { + "start": 3883, + "end": 3884 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 3889, + "end": 3898 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "B", + "span": { + "start": 3901, + "end": 3903 + } + } + ], + "span": { + "start": 3901, + "end": 3903 + } + }, + "span": { + "start": 3902, + "end": 3903 + } + } + ], + "comment": null, + "span": { + "start": 3839, + "end": 3903 + } + }, + { + "type": "Message", + "id": { + "name": "menu-bookmarks-show-all", + "span": { + "start": 3903, + "end": 3926 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3934, + "end": 3939 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Show All Bookmarks", + "span": { + "start": 3942, + "end": 3961 + } + } + ], + "span": { + "start": 3942, + "end": 3961 + } + }, + "span": { + "start": 3960, + "end": 3961 + } + } + ], + "comment": null, + "span": { + "start": 3903, + "end": 3961 + } + }, + { + "type": "Message", + "id": { + "name": "menu-bookmark-this-page", + "span": { + "start": 3961, + "end": 3984 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 3992, + "end": 3997 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmark This Page", + "span": { + "start": 4000, + "end": 4019 + } + } + ], + "span": { + "start": 4000, + "end": 4019 + } + }, + "span": { + "start": 4018, + "end": 4019 + } + } + ], + "comment": null, + "span": { + "start": 3961, + "end": 4019 + } + }, + { + "type": "Message", + "id": { + "name": "menu-bookmark-edit", + "span": { + "start": 4019, + "end": 4037 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4045, + "end": 4050 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Edit This Bookmark", + "span": { + "start": 4053, + "end": 4072 + } + } + ], + "span": { + "start": 4053, + "end": 4072 + } + }, + "span": { + "start": 4071, + "end": 4072 + } + } + ], + "comment": null, + "span": { + "start": 4019, + "end": 4072 + } + }, + { + "type": "Message", + "id": { + "name": "menu-bookmarks-all-tabs", + "span": { + "start": 4072, + "end": 4095 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4103, + "end": 4108 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmark All Tabs…", + "span": { + "start": 4111, + "end": 4132 + } + } + ], + "span": { + "start": 4111, + "end": 4132 + } + }, + "span": { + "start": 4131, + "end": 4132 + } + } + ], + "comment": null, + "span": { + "start": 4072, + "end": 4132 + } + }, + { + "type": "Message", + "id": { + "name": "menu-bookmarks-toolbar", + "span": { + "start": 4132, + "end": 4154 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4162, + "end": 4167 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bookmarks Toolbar", + "span": { + "start": 4170, + "end": 4188 + } + } + ], + "span": { + "start": 4170, + "end": 4188 + } + }, + "span": { + "start": 4187, + "end": 4188 + } + } + ], + "comment": null, + "span": { + "start": 4132, + "end": 4188 + } + }, + { + "type": "Message", + "id": { + "name": "menu-bookmarks-other", + "span": { + "start": 4188, + "end": 4208 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4216, + "end": 4221 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Other Bookmarks", + "span": { + "start": 4224, + "end": 4240 + } + } + ], + "span": { + "start": 4224, + "end": 4240 + } + }, + "span": { + "start": 4239, + "end": 4240 + } + } + ], + "comment": null, + "span": { + "start": 4188, + "end": 4240 + } + }, + { + "type": "Message", + "id": { + "name": "menu-bookmarks-mobile", + "span": { + "start": 4240, + "end": 4261 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4269, + "end": 4274 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Mobile Bookmarks", + "span": { + "start": 4277, + "end": 4294 + } + } + ], + "span": { + "start": 4277, + "end": 4295 + } + }, + "span": { + "start": 4294, + "end": 4295 + } + } + ], + "comment": null, + "span": { + "start": 4240, + "end": 4295 + } + }, + { + "type": "GroupComment", + "content": [ + "Tools Menu" + ], + "span": { + "start": 4295, + "end": 4308 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools", + "span": { + "start": 4310, + "end": 4320 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4328, + "end": 4333 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Tools", + "span": { + "start": 4336, + "end": 4342 + } + } + ], + "span": { + "start": 4336, + "end": 4342 + } + }, + "span": { + "start": 4341, + "end": 4342 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4347, + "end": 4356 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "T", + "span": { + "start": 4359, + "end": 4361 + } + } + ], + "span": { + "start": 4359, + "end": 4361 + } + }, + "span": { + "start": 4360, + "end": 4361 + } + } + ], + "comment": null, + "span": { + "start": 4310, + "end": 4361 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools-downloads", + "span": { + "start": 4361, + "end": 4381 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4389, + "end": 4394 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Downloads", + "span": { + "start": 4397, + "end": 4407 + } + } + ], + "span": { + "start": 4397, + "end": 4407 + } + }, + "span": { + "start": 4406, + "end": 4407 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4412, + "end": 4421 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 4424, + "end": 4426 + } + } + ], + "span": { + "start": 4424, + "end": 4426 + } + }, + "span": { + "start": 4425, + "end": 4426 + } + } + ], + "comment": null, + "span": { + "start": 4361, + "end": 4426 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools-addons", + "span": { + "start": 4426, + "end": 4443 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4451, + "end": 4456 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Add-ons", + "span": { + "start": 4459, + "end": 4467 + } + } + ], + "span": { + "start": 4459, + "end": 4467 + } + }, + "span": { + "start": 4466, + "end": 4467 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4472, + "end": 4481 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A", + "span": { + "start": 4484, + "end": 4486 + } + } + ], + "span": { + "start": 4484, + "end": 4486 + } + }, + "span": { + "start": 4485, + "end": 4486 + } + } + ], + "comment": null, + "span": { + "start": 4426, + "end": 4486 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools-fxa-sign-in", + "span": { + "start": 4486, + "end": 4508 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4516, + "end": 4521 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Sign In To ", + "span": { + "start": 4524, + "end": 4535 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-product-name", + "span": { + "start": 4538, + "end": 4556 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 4537, + "end": 4557 + } + }, + { + "start": 4537, + "end": 4557 + } + ], + "span": { + "start": 4535, + "end": 4557 + } + }, + { + "type": "TextElement", + "value": "…", + "span": { + "start": 4558, + "end": 4562 + } + } + ], + "span": { + "start": 4524, + "end": 4562 + } + }, + "span": { + "start": 4561, + "end": 4562 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4567, + "end": 4576 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "g", + "span": { + "start": 4579, + "end": 4581 + } + } + ], + "span": { + "start": 4579, + "end": 4581 + } + }, + "span": { + "start": 4580, + "end": 4581 + } + } + ], + "comment": null, + "span": { + "start": 4486, + "end": 4581 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools-turn-on-sync", + "span": { + "start": 4581, + "end": 4604 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4612, + "end": 4617 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Turn on ", + "span": { + "start": 4620, + "end": 4628 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "sync-brand-short-name", + "span": { + "start": 4631, + "end": 4652 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 4630, + "end": 4653 + } + }, + { + "start": 4630, + "end": 4653 + } + ], + "span": { + "start": 4628, + "end": 4653 + } + }, + { + "type": "TextElement", + "value": "…", + "span": { + "start": 4654, + "end": 4658 + } + } + ], + "span": { + "start": 4620, + "end": 4658 + } + }, + "span": { + "start": 4657, + "end": 4658 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4663, + "end": 4672 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "n", + "span": { + "start": 4675, + "end": 4677 + } + } + ], + "span": { + "start": 4675, + "end": 4677 + } + }, + "span": { + "start": 4676, + "end": 4677 + } + } + ], + "comment": null, + "span": { + "start": 4581, + "end": 4677 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools-sync-now", + "span": { + "start": 4677, + "end": 4696 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4704, + "end": 4709 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Sync Now", + "span": { + "start": 4712, + "end": 4721 + } + } + ], + "span": { + "start": 4712, + "end": 4721 + } + }, + "span": { + "start": 4720, + "end": 4721 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4726, + "end": 4735 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "S", + "span": { + "start": 4738, + "end": 4740 + } + } + ], + "span": { + "start": 4738, + "end": 4740 + } + }, + "span": { + "start": 4739, + "end": 4740 + } + } + ], + "comment": null, + "span": { + "start": 4677, + "end": 4740 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools-fxa-re-auth", + "span": { + "start": 4740, + "end": 4762 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4770, + "end": 4775 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Reconnect to ", + "span": { + "start": 4778, + "end": 4791 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-product-name", + "span": { + "start": 4794, + "end": 4812 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 4793, + "end": 4813 + } + }, + { + "start": 4793, + "end": 4813 + } + ], + "span": { + "start": 4791, + "end": 4813 + } + }, + { + "type": "TextElement", + "value": "…", + "span": { + "start": 4814, + "end": 4818 + } + } + ], + "span": { + "start": 4778, + "end": 4818 + } + }, + "span": { + "start": 4817, + "end": 4818 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4823, + "end": 4832 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 4835, + "end": 4837 + } + } + ], + "span": { + "start": 4835, + "end": 4837 + } + }, + "span": { + "start": 4836, + "end": 4837 + } + } + ], + "comment": null, + "span": { + "start": 4740, + "end": 4837 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools-web-developer", + "span": { + "start": 4837, + "end": 4861 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4869, + "end": 4874 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Web Developer", + "span": { + "start": 4877, + "end": 4891 + } + } + ], + "span": { + "start": 4877, + "end": 4891 + } + }, + "span": { + "start": 4890, + "end": 4891 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4896, + "end": 4905 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "W", + "span": { + "start": 4908, + "end": 4910 + } + } + ], + "span": { + "start": 4908, + "end": 4910 + } + }, + "span": { + "start": 4909, + "end": 4910 + } + } + ], + "comment": null, + "span": { + "start": 4837, + "end": 4910 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools-page-source", + "span": { + "start": 4910, + "end": 4932 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 4940, + "end": 4945 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Page Source", + "span": { + "start": 4948, + "end": 4960 + } + } + ], + "span": { + "start": 4948, + "end": 4960 + } + }, + "span": { + "start": 4959, + "end": 4960 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 4965, + "end": 4974 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "o", + "span": { + "start": 4977, + "end": 4979 + } + } + ], + "span": { + "start": 4977, + "end": 4979 + } + }, + "span": { + "start": 4978, + "end": 4979 + } + } + ], + "comment": null, + "span": { + "start": 4910, + "end": 4979 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools-page-info", + "span": { + "start": 4979, + "end": 4999 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5007, + "end": 5012 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Page Info", + "span": { + "start": 5015, + "end": 5025 + } + } + ], + "span": { + "start": 5015, + "end": 5025 + } + }, + "span": { + "start": 5024, + "end": 5025 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5030, + "end": 5039 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "I", + "span": { + "start": 5042, + "end": 5044 + } + } + ], + "span": { + "start": 5042, + "end": 5044 + } + }, + "span": { + "start": 5043, + "end": 5044 + } + } + ], + "comment": null, + "span": { + "start": 4979, + "end": 5044 + } + }, + { + "type": "Message", + "id": { + "name": "menu-preferences", + "span": { + "start": 5044, + "end": 5060 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5068, + "end": 5073 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "PLATFORM", + "span": { + "start": 5086, + "end": 5094 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 5094, + "end": 5096 + } + }, + "span": { + "start": 5086, + "end": 5096 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "windows", + "span": { + "start": 5113, + "end": 5120 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Options", + "span": { + "start": 5122, + "end": 5130 + } + } + ], + "span": { + "start": 5122, + "end": 5130 + } + }, + "default": false, + "span": { + "start": 5112, + "end": 5130 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 5143, + "end": 5148 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Preferences", + "span": { + "start": 5150, + "end": 5162 + } + } + ], + "span": { + "start": 5150, + "end": 5162 + } + }, + "default": true, + "span": { + "start": 5141, + "end": 5162 + } + } + ], + "span": { + "start": 5086, + "end": 5170 + } + }, + "span": { + "start": 5084, + "end": 5170 + } + } + ], + "span": { + "start": 5075, + "end": 5172 + } + }, + "span": { + "start": 5171, + "end": 5172 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5177, + "end": 5186 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": { + "selector": { + "type": "FunctionReference", + "id": { + "name": "PLATFORM", + "span": { + "start": 5199, + "end": 5207 + } + }, + "arguments": { + "type": "CallArguments", + "positional": [], + "named": [], + "span": { + "start": 5207, + "end": 5209 + } + }, + "span": { + "start": 5199, + "end": 5209 + } + }, + "variants": [ + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "windows", + "span": { + "start": 5226, + "end": 5233 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "O", + "span": { + "start": 5235, + "end": 5237 + } + } + ], + "span": { + "start": 5235, + "end": 5237 + } + }, + "default": false, + "span": { + "start": 5225, + "end": 5237 + } + }, + { + "type": "Variant", + "key": { + "type": "Identifier", + "name": "other", + "span": { + "start": 5250, + "end": 5255 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "n", + "span": { + "start": 5257, + "end": 5259 + } + } + ], + "span": { + "start": 5257, + "end": 5259 + } + }, + "default": true, + "span": { + "start": 5248, + "end": 5259 + } + } + ], + "span": { + "start": 5199, + "end": 5267 + } + }, + "span": { + "start": 5197, + "end": 5267 + } + } + ], + "span": { + "start": 5188, + "end": 5269 + } + }, + "span": { + "start": 5268, + "end": 5269 + } + } + ], + "comment": null, + "span": { + "start": 5044, + "end": 5269 + } + }, + { + "type": "Message", + "id": { + "name": "menu-tools-layout-debugger", + "span": { + "start": 5269, + "end": 5295 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5303, + "end": 5308 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Layout Debugger", + "span": { + "start": 5311, + "end": 5327 + } + } + ], + "span": { + "start": 5311, + "end": 5327 + } + }, + "span": { + "start": 5326, + "end": 5327 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5332, + "end": 5341 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "L", + "span": { + "start": 5344, + "end": 5346 + } + } + ], + "span": { + "start": 5344, + "end": 5347 + } + }, + "span": { + "start": 5346, + "end": 5347 + } + } + ], + "comment": null, + "span": { + "start": 5269, + "end": 5347 + } + }, + { + "type": "GroupComment", + "content": [ + "Window Menu" + ], + "span": { + "start": 5347, + "end": 5361 + } + }, + { + "type": "Message", + "id": { + "name": "menu-window-menu", + "span": { + "start": 5363, + "end": 5379 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5387, + "end": 5392 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Window", + "span": { + "start": 5395, + "end": 5402 + } + } + ], + "span": { + "start": 5395, + "end": 5402 + } + }, + "span": { + "start": 5401, + "end": 5402 + } + } + ], + "comment": null, + "span": { + "start": 5363, + "end": 5402 + } + }, + { + "type": "Message", + "id": { + "name": "menu-window-bring-all-to-front", + "span": { + "start": 5402, + "end": 5432 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5440, + "end": 5445 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Bring All to Front", + "span": { + "start": 5448, + "end": 5467 + } + } + ], + "span": { + "start": 5448, + "end": 5468 + } + }, + "span": { + "start": 5467, + "end": 5468 + } + } + ], + "comment": null, + "span": { + "start": 5402, + "end": 5468 + } + }, + { + "type": "GroupComment", + "content": [ + "Help Menu" + ], + "span": { + "start": 5468, + "end": 5480 + } + }, + { + "type": "Message", + "id": { + "name": "menu-help", + "span": { + "start": 5482, + "end": 5491 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5499, + "end": 5504 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Help", + "span": { + "start": 5507, + "end": 5512 + } + } + ], + "span": { + "start": 5507, + "end": 5512 + } + }, + "span": { + "start": 5511, + "end": 5512 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5517, + "end": 5526 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "H", + "span": { + "start": 5529, + "end": 5531 + } + } + ], + "span": { + "start": 5529, + "end": 5531 + } + }, + "span": { + "start": 5530, + "end": 5531 + } + } + ], + "comment": null, + "span": { + "start": 5482, + "end": 5531 + } + }, + { + "type": "Message", + "id": { + "name": "menu-help-product", + "span": { + "start": 5531, + "end": 5548 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5556, + "end": 5561 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-shorter-name", + "span": { + "start": 5567, + "end": 5585 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 5566, + "end": 5586 + } + }, + { + "start": 5566, + "end": 5586 + } + ], + "span": { + "start": 5564, + "end": 5586 + } + }, + { + "type": "TextElement", + "value": " Help", + "span": { + "start": 5587, + "end": 5593 + } + } + ], + "span": { + "start": 5564, + "end": 5593 + } + }, + "span": { + "start": 5592, + "end": 5593 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5598, + "end": 5607 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "H", + "span": { + "start": 5610, + "end": 5612 + } + } + ], + "span": { + "start": 5610, + "end": 5612 + } + }, + "span": { + "start": 5611, + "end": 5612 + } + } + ], + "comment": null, + "span": { + "start": 5531, + "end": 5612 + } + }, + { + "type": "Message", + "id": { + "name": "menu-help-show-tour", + "span": { + "start": 5612, + "end": 5631 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5639, + "end": 5644 + } + }, + "value": { + "elements": [ + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-shorter-name", + "span": { + "start": 5650, + "end": 5668 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 5649, + "end": 5669 + } + }, + { + "start": 5649, + "end": 5669 + } + ], + "span": { + "start": 5647, + "end": 5669 + } + }, + { + "type": "TextElement", + "value": " Tour", + "span": { + "start": 5670, + "end": 5676 + } + } + ], + "span": { + "start": 5647, + "end": 5676 + } + }, + "span": { + "start": 5675, + "end": 5676 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5681, + "end": 5690 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "o", + "span": { + "start": 5693, + "end": 5695 + } + } + ], + "span": { + "start": 5693, + "end": 5695 + } + }, + "span": { + "start": 5694, + "end": 5695 + } + } + ], + "comment": null, + "span": { + "start": 5612, + "end": 5695 + } + }, + { + "type": "Message", + "id": { + "name": "menu-help-keyboard-shortcuts", + "span": { + "start": 5695, + "end": 5723 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5731, + "end": 5736 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Keyboard Shortcuts", + "span": { + "start": 5739, + "end": 5758 + } + } + ], + "span": { + "start": 5739, + "end": 5758 + } + }, + "span": { + "start": 5757, + "end": 5758 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5763, + "end": 5772 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "K", + "span": { + "start": 5775, + "end": 5777 + } + } + ], + "span": { + "start": 5775, + "end": 5777 + } + }, + "span": { + "start": 5776, + "end": 5777 + } + } + ], + "comment": null, + "span": { + "start": 5695, + "end": 5777 + } + }, + { + "type": "Message", + "id": { + "name": "menu-help-troubleshooting-info", + "span": { + "start": 5777, + "end": 5807 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5815, + "end": 5820 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Troubleshooting Information", + "span": { + "start": 5823, + "end": 5851 + } + } + ], + "span": { + "start": 5823, + "end": 5851 + } + }, + "span": { + "start": 5850, + "end": 5851 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5856, + "end": 5865 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "T", + "span": { + "start": 5868, + "end": 5870 + } + } + ], + "span": { + "start": 5868, + "end": 5870 + } + }, + "span": { + "start": 5869, + "end": 5870 + } + } + ], + "comment": null, + "span": { + "start": 5777, + "end": 5870 + } + }, + { + "type": "Message", + "id": { + "name": "menu-help-feedback-page", + "span": { + "start": 5870, + "end": 5893 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5901, + "end": 5906 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Submit Feedback…", + "span": { + "start": 5909, + "end": 5928 + } + } + ], + "span": { + "start": 5909, + "end": 5928 + } + }, + "span": { + "start": 5927, + "end": 5928 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 5933, + "end": 5942 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "S", + "span": { + "start": 5945, + "end": 5947 + } + } + ], + "span": { + "start": 5945, + "end": 5947 + } + }, + "span": { + "start": 5946, + "end": 5947 + } + } + ], + "comment": null, + "span": { + "start": 5870, + "end": 5947 + } + }, + { + "type": "Message", + "id": { + "name": "menu-help-safe-mode-without-addons", + "span": { + "start": 5947, + "end": 5981 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 5989, + "end": 5994 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Restart with Add-ons Disabled…", + "span": { + "start": 5997, + "end": 6030 + } + } + ], + "span": { + "start": 5997, + "end": 6030 + } + }, + "span": { + "start": 6029, + "end": 6030 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6035, + "end": 6044 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 6047, + "end": 6049 + } + } + ], + "span": { + "start": 6047, + "end": 6049 + } + }, + "span": { + "start": 6048, + "end": 6049 + } + } + ], + "comment": null, + "span": { + "start": 5947, + "end": 6049 + } + }, + { + "type": "Message", + "id": { + "name": "menu-help-safe-mode-with-addons", + "span": { + "start": 6049, + "end": 6080 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6088, + "end": 6093 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Restart with Add-ons Enabled", + "span": { + "start": 6096, + "end": 6125 + } + } + ], + "span": { + "start": 6096, + "end": 6125 + } + }, + "span": { + "start": 6124, + "end": 6125 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6130, + "end": 6139 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 6142, + "end": 6144 + } + } + ], + "span": { + "start": 6142, + "end": 6144 + } + }, + "span": { + "start": 6143, + "end": 6144 + } + } + ], + "comment": null, + "span": { + "start": 6049, + "end": 6144 + } + }, + { + "type": "Message", + "id": { + "name": "menu-help-report-deceptive-site", + "span": { + "start": 6225, + "end": 6256 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6264, + "end": 6269 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Report Deceptive Site…", + "span": { + "start": 6272, + "end": 6297 + } + } + ], + "span": { + "start": 6272, + "end": 6297 + } + }, + "span": { + "start": 6296, + "end": 6297 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6302, + "end": 6311 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 6314, + "end": 6316 + } + } + ], + "span": { + "start": 6314, + "end": 6316 + } + }, + "span": { + "start": 6315, + "end": 6316 + } + } + ], + "comment": { + "content": [ + "Label of the Help menu item. Either this or", + "menu-help-notdeceptive is shown." + ], + "span": { + "start": 6144, + "end": 6224 + } + }, + "span": { + "start": 6225, + "end": 6316 + } + }, + { + "type": "Message", + "id": { + "name": "menu-help-not-deceptive", + "span": { + "start": 6316, + "end": 6339 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 6347, + "end": 6352 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "This isn’t a deceptive site…", + "span": { + "start": 6355, + "end": 6388 + } + } + ], + "span": { + "start": 6355, + "end": 6388 + } + }, + "span": { + "start": 6387, + "end": 6388 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 6393, + "end": 6402 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "d", + "span": { + "start": 6405, + "end": 6407 + } + } + ], + "span": { + "start": 6405, + "end": 6407 + } + }, + "span": { + "start": 6406, + "end": 6407 + } + } + ], + "comment": null, + "span": { + "start": 6316, + "end": 6407 + } + } + ], + "span": { + "start": 0, + "end": 6407 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/protectionsPanel.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/protectionsPanel.spans.json new file mode 100644 index 00000000..df5f06f1 --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/protectionsPanel.spans.json @@ -0,0 +1,92 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "Message", + "id": { + "name": "protections-panel-sendreportview-error", + "span": { + "start": 200, + "end": 238 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "There was an error sending the report. Please try again later.", + "span": { + "start": 241, + "end": 304 + } + } + ], + "span": { + "start": 241, + "end": 305 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 200, + "end": 305 + } + }, + { + "type": "Message", + "id": { + "name": "protections-panel-sitefixedsendreport-label", + "span": { + "start": 401, + "end": 444 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Site fixed? Send report", + "span": { + "start": 447, + "end": 471 + } + } + ], + "span": { + "start": 447, + "end": 471 + } + }, + "attributes": [], + "comment": { + "content": [ + "A link shown when ETP is disabled for a site. Opens the breakage report subview when clicked." + ], + "span": { + "start": 305, + "end": 400 + } + }, + "span": { + "start": 401, + "end": 471 + } + } + ], + "span": { + "start": 0, + "end": 471 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/sync-brand.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/sync-brand.spans.json new file mode 100644 index 00000000..1288e657 --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/sync-brand.spans.json @@ -0,0 +1,134 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "Term", + "id": { + "name": "sync-brand-short-name", + "span": { + "start": 201, + "end": 222 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Sync", + "span": { + "start": 225, + "end": 230 + } + } + ], + "span": { + "start": 225, + "end": 231 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 200, + "end": 231 + } + }, + { + "type": "Term", + "id": { + "name": "sync-brand-name", + "span": { + "start": 328, + "end": 343 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Firefox Sync", + "span": { + "start": 346, + "end": 359 + } + } + ], + "span": { + "start": 346, + "end": 360 + } + }, + "attributes": [], + "comment": { + "content": [ + "“Sync” can be localized, “Firefox” must be treated as a brand,", + "and kept in English." + ], + "span": { + "start": 231, + "end": 326 + } + }, + "span": { + "start": 327, + "end": 360 + } + }, + { + "type": "Term", + "id": { + "name": "fxaccount-brand-name", + "span": { + "start": 460, + "end": 480 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Firefox Account", + "span": { + "start": 483, + "end": 499 + } + } + ], + "span": { + "start": 483, + "end": 499 + } + }, + "attributes": [], + "comment": { + "content": [ + "“Account” can be localized, “Firefox” must be treated as a brand,", + "and kept in English." + ], + "span": { + "start": 360, + "end": 458 + } + }, + "span": { + "start": 459, + "end": 499 + } + } + ], + "span": { + "start": 0, + "end": 499 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/browser/textActions.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/browser/textActions.spans.json new file mode 100644 index 00000000..94e87939 --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/browser/textActions.spans.json @@ -0,0 +1,834 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-undo", + "span": { + "start": 200, + "end": 216 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 224, + "end": 229 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Undo", + "span": { + "start": 232, + "end": 237 + } + } + ], + "span": { + "start": 232, + "end": 237 + } + }, + "span": { + "start": 236, + "end": 237 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 242, + "end": 251 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "U", + "span": { + "start": 254, + "end": 256 + } + } + ], + "span": { + "start": 254, + "end": 257 + } + }, + "span": { + "start": 256, + "end": 257 + } + } + ], + "comment": null, + "span": { + "start": 200, + "end": 257 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-undo-shortcut", + "span": { + "start": 257, + "end": 282 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 290, + "end": 293 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Z", + "span": { + "start": 296, + "end": 298 + } + } + ], + "span": { + "start": 296, + "end": 299 + } + }, + "span": { + "start": 298, + "end": 299 + } + } + ], + "comment": null, + "span": { + "start": 257, + "end": 299 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-redo", + "span": { + "start": 299, + "end": 315 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 323, + "end": 328 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Redo", + "span": { + "start": 331, + "end": 336 + } + } + ], + "span": { + "start": 331, + "end": 336 + } + }, + "span": { + "start": 335, + "end": 336 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 341, + "end": 350 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 353, + "end": 355 + } + } + ], + "span": { + "start": 353, + "end": 356 + } + }, + "span": { + "start": 355, + "end": 356 + } + } + ], + "comment": null, + "span": { + "start": 299, + "end": 356 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-redo-shortcut", + "span": { + "start": 356, + "end": 381 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 389, + "end": 392 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Y", + "span": { + "start": 395, + "end": 397 + } + } + ], + "span": { + "start": 395, + "end": 398 + } + }, + "span": { + "start": 397, + "end": 398 + } + } + ], + "comment": null, + "span": { + "start": 356, + "end": 398 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-cut", + "span": { + "start": 398, + "end": 413 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 421, + "end": 426 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Cut", + "span": { + "start": 429, + "end": 433 + } + } + ], + "span": { + "start": 429, + "end": 433 + } + }, + "span": { + "start": 432, + "end": 433 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 438, + "end": 447 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "t", + "span": { + "start": 450, + "end": 452 + } + } + ], + "span": { + "start": 450, + "end": 453 + } + }, + "span": { + "start": 452, + "end": 453 + } + } + ], + "comment": null, + "span": { + "start": 398, + "end": 453 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-cut-shortcut", + "span": { + "start": 453, + "end": 477 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 485, + "end": 488 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "X", + "span": { + "start": 491, + "end": 493 + } + } + ], + "span": { + "start": 491, + "end": 494 + } + }, + "span": { + "start": 493, + "end": 494 + } + } + ], + "comment": null, + "span": { + "start": 453, + "end": 494 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-copy", + "span": { + "start": 494, + "end": 510 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 518, + "end": 523 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Copy", + "span": { + "start": 526, + "end": 531 + } + } + ], + "span": { + "start": 526, + "end": 531 + } + }, + "span": { + "start": 530, + "end": 531 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 536, + "end": 545 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "C", + "span": { + "start": 548, + "end": 550 + } + } + ], + "span": { + "start": 548, + "end": 551 + } + }, + "span": { + "start": 550, + "end": 551 + } + } + ], + "comment": null, + "span": { + "start": 494, + "end": 551 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-copy-shortcut", + "span": { + "start": 551, + "end": 576 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 584, + "end": 587 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "C", + "span": { + "start": 590, + "end": 592 + } + } + ], + "span": { + "start": 590, + "end": 593 + } + }, + "span": { + "start": 592, + "end": 593 + } + } + ], + "comment": null, + "span": { + "start": 551, + "end": 593 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-paste", + "span": { + "start": 593, + "end": 610 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 618, + "end": 623 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Paste", + "span": { + "start": 626, + "end": 632 + } + } + ], + "span": { + "start": 626, + "end": 632 + } + }, + "span": { + "start": 631, + "end": 632 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 637, + "end": 646 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "P", + "span": { + "start": 649, + "end": 651 + } + } + ], + "span": { + "start": 649, + "end": 652 + } + }, + "span": { + "start": 651, + "end": 652 + } + } + ], + "comment": null, + "span": { + "start": 593, + "end": 652 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-paste-shortcut", + "span": { + "start": 652, + "end": 678 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 686, + "end": 689 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "V", + "span": { + "start": 692, + "end": 694 + } + } + ], + "span": { + "start": 692, + "end": 695 + } + }, + "span": { + "start": 694, + "end": 695 + } + } + ], + "comment": null, + "span": { + "start": 652, + "end": 695 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-delete", + "span": { + "start": 695, + "end": 713 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 721, + "end": 726 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Delete", + "span": { + "start": 729, + "end": 736 + } + } + ], + "span": { + "start": 729, + "end": 736 + } + }, + "span": { + "start": 735, + "end": 736 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 741, + "end": 750 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "D", + "span": { + "start": 753, + "end": 755 + } + } + ], + "span": { + "start": 753, + "end": 756 + } + }, + "span": { + "start": 755, + "end": 756 + } + } + ], + "comment": null, + "span": { + "start": 695, + "end": 756 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-select-all", + "span": { + "start": 756, + "end": 778 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 786, + "end": 791 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Select All", + "span": { + "start": 794, + "end": 805 + } + } + ], + "span": { + "start": 794, + "end": 805 + } + }, + "span": { + "start": 804, + "end": 805 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 810, + "end": 819 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A", + "span": { + "start": 822, + "end": 824 + } + } + ], + "span": { + "start": 822, + "end": 825 + } + }, + "span": { + "start": 824, + "end": 825 + } + } + ], + "comment": null, + "span": { + "start": 756, + "end": 825 + } + }, + { + "type": "Message", + "id": { + "name": "text-action-select-all-shortcut", + "span": { + "start": 825, + "end": 856 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "key", + "span": { + "start": 864, + "end": 867 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "A", + "span": { + "start": 870, + "end": 872 + } + } + ], + "span": { + "start": 870, + "end": 872 + } + }, + "span": { + "start": 871, + "end": 872 + } + } + ], + "comment": null, + "span": { + "start": 825, + "end": 872 + } + } + ], + "span": { + "start": 0, + "end": 872 + } +} \ No newline at end of file diff --git a/fluent-syntax/tests/fixtures/benches/contexts/preferences/aboutDialog.spans.json b/fluent-syntax/tests/fixtures/benches/contexts/preferences/aboutDialog.spans.json new file mode 100644 index 00000000..2d38236e --- /dev/null +++ b/fluent-syntax/tests/fixtures/benches/contexts/preferences/aboutDialog.spans.json @@ -0,0 +1,1353 @@ +{ + "body": [ + { + "type": "Comment", + "content": [ + "This Source Code Form is subject to the terms of the Mozilla Public", + "License, v. 2.0. If a copy of the MPL was not distributed with this", + "file, You can obtain one at http://mozilla.org/MPL/2.0/." + ], + "span": { + "start": 0, + "end": 198 + } + }, + { + "type": "Message", + "id": { + "name": "aboutDialog-title", + "span": { + "start": 200, + "end": 217 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "title", + "span": { + "start": 225, + "end": 230 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "About ", + "span": { + "start": 233, + "end": 239 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-full-name", + "span": { + "start": 242, + "end": 257 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 241, + "end": 258 + } + }, + { + "start": 241, + "end": 258 + } + ], + "span": { + "start": 239, + "end": 258 + } + } + ], + "span": { + "start": 233, + "end": 261 + } + }, + "span": { + "start": 260, + "end": 261 + } + } + ], + "comment": null, + "span": { + "start": 200, + "end": 261 + } + }, + { + "type": "Message", + "id": { + "name": "releaseNotes-link", + "span": { + "start": 261, + "end": 278 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "What’s new", + "span": { + "start": 281, + "end": 294 + } + } + ], + "span": { + "start": 281, + "end": 295 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 261, + "end": 295 + } + }, + { + "type": "Message", + "id": { + "name": "update-checkForUpdatesButton", + "span": { + "start": 295, + "end": 323 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 331, + "end": 336 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Check for updates", + "span": { + "start": 339, + "end": 357 + } + } + ], + "span": { + "start": 339, + "end": 357 + } + }, + "span": { + "start": 356, + "end": 357 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 362, + "end": 371 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "C", + "span": { + "start": 374, + "end": 376 + } + } + ], + "span": { + "start": 374, + "end": 377 + } + }, + "span": { + "start": 376, + "end": 377 + } + } + ], + "comment": null, + "span": { + "start": 295, + "end": 377 + } + }, + { + "type": "Message", + "id": { + "name": "update-updateButton", + "span": { + "start": 377, + "end": 396 + } + }, + "value": null, + "attributes": [ + { + "id": { + "name": "label", + "span": { + "start": 404, + "end": 409 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Restart to update ", + "span": { + "start": 412, + "end": 430 + } + }, + { + "type": "Placeable", + "expression": [ + { + "type": "TermReference", + "id": { + "name": "brand-shorter-name", + "span": { + "start": 433, + "end": 451 + } + }, + "attribute": null, + "arguments": null, + "span": { + "start": 432, + "end": 452 + } + }, + { + "start": 432, + "end": 452 + } + ], + "span": { + "start": 430, + "end": 452 + } + } + ], + "span": { + "start": 412, + "end": 454 + } + }, + "span": { + "start": 453, + "end": 454 + } + }, + { + "id": { + "name": "accesskey", + "span": { + "start": 459, + "end": 468 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "R", + "span": { + "start": 471, + "end": 473 + } + } + ], + "span": { + "start": 471, + "end": 474 + } + }, + "span": { + "start": 473, + "end": 474 + } + } + ], + "comment": null, + "span": { + "start": 377, + "end": 474 + } + }, + { + "type": "Message", + "id": { + "name": "update-checkingForUpdates", + "span": { + "start": 474, + "end": 499 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Checking for updates…", + "span": { + "start": 502, + "end": 526 + } + } + ], + "span": { + "start": 502, + "end": 526 + } + }, + "attributes": [], + "comment": null, + "span": { + "start": 474, + "end": 526 + } + }, + { + "type": "Message", + "id": { + "name": "update-downloading", + "span": { + "start": 526, + "end": 544 + } + }, + "value": { + "elements": [ + { + "type": "TextElement", + "value": "Downloading update —