diff --git a/exploration/expression-attributes.md b/exploration/expression-attributes.md
index 2edde5613..0253fc49e 100644
--- a/exploration/expression-attributes.md
+++ b/exploration/expression-attributes.md
@@ -1,6 +1,6 @@
# Expression Attributes
-Status: **Proposed**
+Status: **Accepted**
Metadata
@@ -15,6 +15,8 @@ Status: **Proposed**
#772
#780
#792
+ #845
+ #846
diff --git a/spec/data-model/README.md b/spec/data-model/README.md
index 517596f1c..9084e0203 100644
--- a/spec/data-model/README.md
+++ b/spec/data-model/README.md
@@ -203,8 +203,6 @@ interface UnsupportedExpression {
annotation: UnsupportedAnnotation;
attributes: Attributes;
}
-
-type Attributes = Map;
```
## Expressions
@@ -283,6 +281,17 @@ interface Markup {
}
```
+## Attributes
+
+`Attributes` is a key-value mapping
+used to represent the _expression_ and _markup_ _attributes_.
+
+_Attributes_ with no value are represented by `true` here.
+
+```ts
+type Attributes = Map;
+```
+
## Extensions
Implementations MAY extend this data model with additional interfaces,
diff --git a/spec/data-model/message.dtd b/spec/data-model/message.dtd
index 33be40df2..6c49c358a 100644
--- a/spec/data-model/message.dtd
+++ b/spec/data-model/message.dtd
@@ -41,7 +41,7 @@
-
+
diff --git a/spec/data-model/message.json b/spec/data-model/message.json
index 77fc3a4f4..ae2867d2c 100644
--- a/spec/data-model/message.json
+++ b/spec/data-model/message.json
@@ -32,7 +32,7 @@
"attributes": {
"type": "object",
"additionalProperties": {
- "oneOf": [{ "$ref": "#/$defs/literal-or-variable" }, { "const": true }]
+ "oneOf": [{ "$ref": "#/$defs/literal" }, { "const": true }]
}
},
diff --git a/spec/formatting.md b/spec/formatting.md
index dc3719b10..0acaa7894 100644
--- a/spec/formatting.md
+++ b/spec/formatting.md
@@ -58,6 +58,8 @@ or even use them in their internal processing,
as long as the final _formatting_ result is made available to users
and the observable behavior of the formatter matches that described here.
+_Attributes_ MUST NOT affect the processing or output of a _message_.
+
## Formatting Context
A message's **_formatting context_** represents the data and procedures that are required
@@ -762,10 +764,6 @@ MUST be an empty string.
Implementations MAY offer functionality for customizing this,
such as by emitting XML-ish tags for each _markup_.
-_Attributes_ are reserved for future standardization.
-Other than checking for valid syntax, they SHOULD NOT
-affect the processing or output of a _message_.
-
### Examples
_This section is non-normative._
diff --git a/spec/syntax.md b/spec/syntax.md
index 42d742ef1..76fc74502 100644
--- a/spec/syntax.md
+++ b/spec/syntax.md
@@ -90,7 +90,7 @@ Attempting to parse a _message_ that is not _well-formed_ will result in a _Synt
A _message_ is **_valid_** if it is _well-formed_ and
**also** meets the additional content restrictions
and semantic requirements about its structure defined below for
-_declarations_, _matcher_ and _options_.
+_declarations_, _matcher_, _options_, and _attributes_.
Attempting to parse a _message_ that is not _valid_ will result in a _Data Model Error_.
## The Message
@@ -154,7 +154,7 @@ message = simple-message / complex-message
A **_simple message_** contains a single _pattern_,
with restrictions on its first non-whitespace character.
-An empty string is a valid _simple message_.
+An empty string is a _valid_ _simple message_.
Whitespace at the start or end of a _simple message_ is significant,
and a part of the _text_ of the _message_.
@@ -445,7 +445,7 @@ There MAY be any number of additional _selectors_.
A **_variant_** is a _quoted pattern_ associated with a list of _keys_ in a _matcher_.
Each _variant_ MUST begin with a sequence of _keys_,
-and terminate with a valid _quoted pattern_.
+and terminate with a _valid_ _quoted pattern_.
The number of _keys_ in each _variant_ MUST match the number of _selectors_ in the _matcher_.
Each _key_ is separated from each other by whitespace.
@@ -555,7 +555,7 @@ A _function_'s entry in the _function registry_ will define
whether the _function_ is a _selector_ or formatter (or both),
whether an _operand_ is required,
what form the values of an _operand_ can take,
-what _options_ and _option_ values are valid,
+what _options_ and _option_ values are acceptable,
and what outputs might result.
See [function registry](./registry.md) for more information.
@@ -587,7 +587,7 @@ Multiple _options_ are permitted in an _annotation_.
_Options_ are separated from the preceding _function_ _identifier_
and from each other by whitespace.
Each _option_'s _identifier_ MUST be unique within the _annotation_:
-an _annotation_ with duplicate _option_ _identifiers_ is not valid.
+an _annotation_ with duplicate _option_ _identifiers_ is not _valid_.
The order of _options_ is not significant.
@@ -723,7 +723,8 @@ markup = "{" [s] "#" identifier *(s option) *(s attribute) [s] ["/"] "}" ; open
> {#button}Submit{/button} or {#img alt=|Cancel| /}.
> ```
-> A _message_ with attributes in the closing tag:
+> A _message_ containing _markup_ that uses _options_ to pair
+> two closing markup _placeholders_ to the one open markup _placeholder_:
>
> ```
> {#ansi attr=|bold,italic|}Bold and italic{/ansi attr=|bold|} italic only {/ansi attr=|italic|} no formatting.}
@@ -737,66 +738,25 @@ on the pairing, ordering, or contents of _markup_ during _formatting_.
## Attributes
-**_Attributes_ are reserved for standardization by future versions of this specification._**
-Examples in this section are meant to be illustrative and
-might not match future requirements or usage.
-
-> [!NOTE]
-> The Tech Preview does not provide a built-in mechanism for overriding
-> values in the _formatting context_ (most notably the locale)
-> Nor does it provide a mechanism for identifying specific expressions
-> such as by assigning a name or id.
-> The utility of these types of mechanisms has been debated.
-> There are at least two proposed mechanisms for implementing support for
-> these.
-> Specifically, one mechanism would be to reserve specifically-named options,
-> possibly using a Unicode namespace (i.e. `locale=xxx` or `u:locale=xxx`).
-> Such options would be reserved for use in any and all functions or markup.
-> The other mechanism would be to use the reserved "expression attribute" syntax
-> for this purpose (i.e. `@locale=xxx` or `@id=foo`)
-> Neither mechanism was included in this Tech Preview.
-> Feedback on the preferred mechanism for managing these features
-> is strongly desired.
->
-> In the meantime, function authors and other implementers are cautioned to avoid creating
-> function-specific or implementation-specific option values for this purpose.
-> One workaround would be to use the implementation's namespace for these
-> features to insure later interoperability when such a mechanism is finalized
-> during the Tech Preview period.
-> Specifically:
-> - Avoid specifying an option for setting the locale of an expression as different from
-> that of the overall _message_ locale, or use a namespace that later maps to the final
-> mechanism.
-> - Avoid specifying options for the purpose of linking placeholders
-> (such as to pair opening markup to closing markup).
-> If such an option is created, the implementer should use an
-> implementation-specific namespace.
-> Users and implementers are cautioned that such options might be
-> replaced with a standard mechanism in a future version.
-> - Avoid specifying generic options to communicate with translators and
-> translation tooling (i.e. implementation-specific options that apply to all
-> functions.
-> The above are all desirable features.
-> We welcome contributions to and proposals for such features during the
-> Technical Preview.
-
An **_attribute_** is an _identifier_ with an optional value
that appears in an _expression_ or in _markup_.
+During formatting, _attributes_ have no effect,
+and they can be treated as code comments.
_Attributes_ are prefixed by a U+0040 COMMERCIAL AT `@` sign,
followed by an _identifier_.
-An _attribute_ MAY have a _value_ which is separated from the _identifier_
+An _attribute_ MAY have a _literal_ _value_ which is separated from the _identifier_
by an U+003D EQUALS SIGN `=` along with optional whitespace.
-The _value_ of an _attribute_ can be either a _literal_ or a _variable_.
Multiple _attributes_ are permitted in an _expression_ or _markup_.
Each _attribute_ is separated by whitespace.
+Each _attribute_'s _identifier_ MUST be unique within the _expression_ or _markup_:
+an _expression_ or _markup_ with duplicate _attribute_ _identifiers_ is not _valid_.
The order of _attributes_ is not significant.
-
```abnf
-attribute = "@" identifier [[s] "=" [s] (literal / variable)]
+attribute = "@" identifier [[s] "=" [s] literal]
```
> Examples of _expressions_ and _markup_ with _attributes_: