diff --git a/_components/header.vto b/_components/header.vto new file mode 100644 index 0000000..76be624 --- /dev/null +++ b/_components/header.vto @@ -0,0 +1,42 @@ + +
+ + + + + + + + + +
\ No newline at end of file diff --git a/_includes/example.vto b/_includes/example.vto new file mode 100644 index 0000000..9fd0f94 --- /dev/null +++ b/_includes/example.vto @@ -0,0 +1,27 @@ +--- +layout: layout.vto +--- + +{{ comp.header({ title: "Examples" }) }} + +
+
+
+

← Back to Overview

+

{{ title }}

+

{{ description }}

+
{{ content }}
+ {{ if related && related.length > 0 }} +

Related

+ + {{ /if }} + {{ comp.footer({ padding: "" }) }} +
+
+
diff --git a/_includes/layout.vto b/_includes/layout.vto index 356b09a..5d2f138 100644 --- a/_includes/layout.vto +++ b/_includes/layout.vto @@ -9,7 +9,7 @@ {{ /if }} - {{ if url.startsWith('/docs/') }} + {{ if url.startsWith('/docs/') || url.startsWith('/examples/') }} {{ /if }} {{ if url == '/playground/' }} diff --git a/docs/_data.yml b/docs/_data.yml index 9fb081a..9006515 100644 --- a/docs/_data.yml +++ b/docs/_data.yml @@ -3,6 +3,7 @@ sidebar: - docs/quick-start/ - docs/why/ - docs/translators/ + - examples/ - section: Reference children: - docs/reference/functions/ diff --git a/examples.vto b/examples.vto new file mode 100644 index 0000000..1214c59 --- /dev/null +++ b/examples.vto @@ -0,0 +1,45 @@ +--- +layout: layout.vto +title: Examples +sections: + - numbers + - variants +--- + +{{ comp.header({ title: "Examples" }) }} + +
+

Examples

+
+

MessageFormat 2 is a powerful and flexible language for creating localized messages. This examples catalog showcases a variety of common use cases and how to solve them with MessageFormat 2.

+ +

Each example includes an interactive playground where you can experiment with the code and see the output in real-time. The examples are organized by category.

+ +
+ Looking for a structured walkthrough of MessageFormat 2 instead? Check out the Quick Start. +
+
+ + +
+ {{ for section of sections }} +
+

{{ search.page(`example_${section}`).section }}

+ +
+ {{ /for }} +
+ + + {{ comp.footer({ padding: "" }) }} +
+ diff --git a/examples/_data.yml b/examples/_data.yml new file mode 100644 index 0000000..b3fd5e0 --- /dev/null +++ b/examples/_data.yml @@ -0,0 +1 @@ +layout: example.vto diff --git a/examples/numbers/_data.yml b/examples/numbers/_data.yml new file mode 100644 index 0000000..bf735f1 --- /dev/null +++ b/examples/numbers/_data.yml @@ -0,0 +1,3 @@ +section: Numbers +tags: + - example_numbers diff --git a/examples/numbers/compact-notation.md b/examples/numbers/compact-notation.md new file mode 100644 index 0000000..6e3b508 --- /dev/null +++ b/examples/numbers/compact-notation.md @@ -0,0 +1,38 @@ +--- +title: Compact notation +description: Print numbers in compact notation, such as 100K or 1.23M. +related: + - examples/numbers/rounding-and-precision/ +--- + + + +```mf2 +{ 123456 :number notation=compact } +``` + + + + + +```mf2 +{ 123456 :number notation=compact compactDisplay=long } +``` + + + +Compact notation is a way of expressing large numbers in a more concise form. It +is commonly used in financial and scientific applications. + +The denominator of the compact form is a power of 10. In US English, examples +are 1,000 (K), 1,000,000 (M), or 1,000,000,000 (B). In other locales, different +denominators may be used, which may not always be a power of 1000. In India, for +example, 1,00,000 (L) is used to represent 100,000. + + + +```mf2 +{ 123456 :number notation=compact } +``` + + diff --git a/examples/numbers/engineering-notation.md b/examples/numbers/engineering-notation.md new file mode 100644 index 0000000..ac8559d --- /dev/null +++ b/examples/numbers/engineering-notation.md @@ -0,0 +1,18 @@ +--- +title: Engineering notation +description: Print numbers in engineering notation, such as 123.45E3. +related: + - examples/numbers/rounding-and-precision/ +--- + + + +```mf2 +{ 12345 :number notation=engineering } +``` + + + +[Engineering notation](https://en.wikipedia.org/wiki/Engineering_notation) is a +variant of scientific notation in which the exponent is a multiple of three. It +is commonly used in engineering and scientific applications. diff --git a/examples/numbers/padding.md b/examples/numbers/padding.md new file mode 100644 index 0000000..9baab03 --- /dev/null +++ b/examples/numbers/padding.md @@ -0,0 +1,21 @@ +--- +title: Padding with zeros +description: Pad numbers with zeros to a specific width. +related: + - examples/numbers/rounding-and-precision/ +--- + + + +```mf2 +{ 3 :number minimumIntegerDigits=3 } +``` + + + +Some applications require numbers to be padded with zeros to a specific width. +This is often the case when numbers are displayed in a fixed-width font or +formatted as part of a larger string. + +The minimum number of integer digits can be specified using the +`minimumIntegerDigits` option. Any missing digits are filled with zeros. diff --git a/examples/numbers/percent.md b/examples/numbers/percent.md new file mode 100644 index 0000000..0969f40 --- /dev/null +++ b/examples/numbers/percent.md @@ -0,0 +1,17 @@ +--- +title: Displaying percentages +description: Display fractional numbers as percentages, such as 0.5 as 50%. +related: + - examples/numbers/rounding-and-precision/ +--- + + + +```mf2 +{ 0.5 :number style=percent } +``` + + + +Percentages are a way of expressing numbers as fractions of 100. They are +commonly used in financial and scientific applications. diff --git a/examples/numbers/rounding-and-precision.md b/examples/numbers/rounding-and-precision.md new file mode 100644 index 0000000..348c2fc --- /dev/null +++ b/examples/numbers/rounding-and-precision.md @@ -0,0 +1,58 @@ +--- +title: Rounding and precision +description: Round numbers to a specific number of decimal places or significant digits. +related: + - examples/numbers/scientific-notation/ +--- + +## Fractional digits + +Fractional digits are the number of digits to the right of the decimal point in +a number. + + + +```mf2 +{ 3.12345 :number maximumFractionDigits=2 } +``` + + + + + +```mf2 +{ 3 :number minimumFractionDigits=3 } +``` + + + +When using the `minimumFractionDigits` option, any missing decimal places in the +original number are filled with zeros. + +## Significant digits + +[Significant digits](https://en.wikipedia.org/wiki/Significant_figures) are the +number of digits that carry meaning in a number. They are used to indicate the +precision of a measurement or calculation. + +Any leading zeros are not considered significant. For example, `0.00123` has 3 +significant digits, while `0.001230` has 4 significant digits. + + + +```mf2 +{ 12.34 :number maximumSignificantDigits=3 } +``` + + + + + +```mf2 +{ 3 :number minimumSignificantDigits=3 } +``` + + + +When using the `minimumSignificantDigits` option, any missing significant digits +in the original number are filled with zeros. diff --git a/examples/numbers/scientific-notation.md b/examples/numbers/scientific-notation.md new file mode 100644 index 0000000..82cb40f --- /dev/null +++ b/examples/numbers/scientific-notation.md @@ -0,0 +1,21 @@ +--- +title: Scientific notation +description: Print numbers in scientific notation, such as 1.001E2. +related: + - examples/numbers/rounding-and-precision/ +--- + + + +```mf2 +{ 100.100 :number notation=scientific } +``` + + + +[Scientific notation](https://en.wikipedia.org/wiki/Scientific_notation) is a +way of expressing numbers that are too large or too small to be conveniently +written in decimal form. It is commonly used in scientific applications. + +To print a number in scientific notation, use the `:number` function with the +`notation=scientific` option. diff --git a/examples/numbers/sign-display.md b/examples/numbers/sign-display.md new file mode 100644 index 0000000..5d7ecf2 --- /dev/null +++ b/examples/numbers/sign-display.md @@ -0,0 +1,42 @@ +--- +title: Displaying or hiding the sign +description: (Forcibly) display or hide the sign of a number. +--- + + + +```mf2 +{ 1 :number signDisplay=always } +{ -1 :number signDisplay=always } +``` + + + + + +```mf2 +{ 1 :number signDisplay=never } +{ -1 :number signDisplay=never } +``` + + + +By default, positive numbers are not prefixed with a sign, while negative +numbers are prefixed with a minus sign. + +The `signDisplay` option can be used to forcibly display or hide the sign of a +number. The possible values are: + +- `auto` (default): Display the sign only for negative numbers, including + negative zero. +- `always`: Always display the sign, even for positive numbers, and positive + zero. +- `never`: Never display the sign, even for negative numbers, and negative zero. +- `exceptZero`: Display the sign for all numbers, except for zero. +- `negative`: Display the sign only for negative numbers, but not for negative + zero. + +> Floating-point numbers distinguish between positive and negative zero. In +> modes `auto` and `always`, the sign of negative zero is displayed. If you do +> not want to display the sign for negative zero, use `negative` instead of +> `auto`, or `exceptZero` instead of `always`. diff --git a/examples/variants/_data.yml b/examples/variants/_data.yml new file mode 100644 index 0000000..6df8644 --- /dev/null +++ b/examples/variants/_data.yml @@ -0,0 +1,3 @@ +section: Variants +tags: + - example_variants diff --git a/examples/variants/ordinal-numerals.md b/examples/variants/ordinal-numerals.md new file mode 100644 index 0000000..5785629 --- /dev/null +++ b/examples/variants/ordinal-numerals.md @@ -0,0 +1,37 @@ +--- +title: Ordinal numerals +description: Display ordinal numerals for given numbers, such as `1st`, `2nd`, `3rd`, etc. +--- + + + +```mf2 +.input {$number :number select=ordinal} +.match $number + one {{The {$number}st item.}} + two {{The {$number}nd item.}} + few {{The {$number}rd item.}} + * {{The {$number}th item.}} +``` + +```json +{ "number": 1 } +``` + + + +Ordinal numerals are a way of expressing numbers as a position in a sequence. +They are commonly used in lists, rankings, and other ordered collections. + +In English, the ordinal numerals are formed by adding a suffix to the number. +For numbers ending in 1, 2, and 3, the suffixes are `st`, `nd`, and `rd`, +respectively (with exceptions for 11, 12, and 13). For all other numbers, the +suffix is `th`. + +In many other languages, the rules for forming ordinal numerals are different. +Some languages have just one suffix, like German or Dutch with `te` or `de`, +respectively. + +The +[full set of ordinal rules](https://www.unicode.org/cldr/charts/47/supplemental/language_plural_rules.html) +for each locale is defined in the Unicode Common Locale Data Repository (CLDR). diff --git a/examples/variants/pluralization.md b/examples/variants/pluralization.md new file mode 100644 index 0000000..fdb2b45 --- /dev/null +++ b/examples/variants/pluralization.md @@ -0,0 +1,58 @@ +--- +title: Pluralization +description: Display different messages based on the number of items. +--- + + + +```mf2 +.input {$count :number} +.match $count + 0 {{There are no items.}} + one {{There is one item.}} + * {{There are {$count} items.}} +``` + +```json +{ "count": 1 } +``` + + + +Pluralization is a way of expressing different messages based on the number of +items. It is commonly used in user interfaces to provide feedback on the number +of items in a list, for example. + +In different locales, the rules for pluralization can vary. In English, for +example, there are two plural forms: one for the singular and one for the +plural. In other languages, there may be more plural forms, such as a separate +form for zero, or for numbers ending in 2, 3, or 4. + +In Czech, for example, the plural forms are: + +- `one`: 1 item +- `few`: 2, 3, or 4 items +- `many`: numbers with a decimal part +- `other`: all integers 5 and up + + + +```mf2 +.input {$count :number} +.match $count + 0 {{Zde nejsou žádné prvky.}} + one {{Je zde jeden prvek.}} + few {{Jsou zde {$count} prvky.}} + many {{Jsou zde {$count} prvků.}} + * {{Jsou zde {$count} prvků.}} +``` + +```json +{ "count": 3 } +``` + + + +The +[full set of plural forms](https://www.unicode.org/cldr/charts/47/supplemental/language_plural_rules.html) +for each locale is defined in the Unicode Common Locale Data Repository (CLDR). diff --git a/index.tsx b/index.tsx index 71560f1..04136c2 100644 --- a/index.tsx +++ b/index.tsx @@ -49,6 +49,12 @@ export default function IndexPage({ comp }: any) { > Documentation + + Examples + diff --git a/playground.tsx b/playground.tsx index 174204a..1f8564f 100644 --- a/playground.tsx +++ b/playground.tsx @@ -3,7 +3,7 @@ export const layout = "layout.vto"; export const title = "Playground"; // deno-lint-ignore no-explicit-any -export default function IndexPage({ comp }: any) { +export default function PlaygroundPage({ comp }: any) { return ( <>
diff --git a/src/_utils/encode.ts b/src/_utils/encode.ts new file mode 100644 index 0000000..9513e49 --- /dev/null +++ b/src/_utils/encode.ts @@ -0,0 +1,11 @@ +export function encode(source: string): string { + const textEncoder = new TextEncoder(); + const encoded = textEncoder.encode(source); + return btoa(String.fromCharCode(...encoded)); +} + +export function decode(encoded: string): string { + const textDecoder = new TextDecoder(); + const decoded = atob(encoded); + return textDecoder.decode(Uint8Array.from(decoded, c => c.charCodeAt(0))); +} \ No newline at end of file diff --git a/src/interactive.entry.ts b/src/interactive.entry.ts index 231019b..2d48b45 100644 --- a/src/interactive.entry.ts +++ b/src/interactive.entry.ts @@ -1,3 +1,4 @@ +import { encode } from "./_utils/encode.ts"; import { formatMessageToHTML, MessageFormat } from "./_utils/message_format.ts"; import { jsonHighlight } from "./highlighters/json.ts"; import { mf2Highlight } from "./highlighters/mf2.ts"; @@ -134,9 +135,9 @@ export class Mf2Interactive extends HTMLElement { this.#output.classList.remove("error"); this.#output.innerHTML = ""; - const encodedMessage = btoa(code); - const encodedData = btoa(data); - const encodedLocale = btoa(this.#locale); + const encodedMessage = encode(code); + const encodedData = encode(data); + const encodedLocale = encode(this.#locale); const hash = `#${encodedMessage}.${encodedData}.${encodedLocale}` .replaceAll("/", "_").replaceAll("+", "-").replaceAll("=", ""); this.#share.href = `/playground/${hash}`; diff --git a/src/playground.entry.ts b/src/playground.entry.ts index 3d986b2..97fc560 100644 --- a/src/playground.entry.ts +++ b/src/playground.entry.ts @@ -6,6 +6,7 @@ import { type HighlightedTextarea } from "./textarea.ts"; import "./textarea.ts"; import { mf2Highlight } from "./highlighters/mf2.ts"; import { jsonHighlight } from "./highlighters/json.ts"; +import { decode, encode } from "./_utils/encode.ts"; globalThis.addEventListener("DOMContentLoaded", () => { const supportedLocales = locales.all @@ -118,9 +119,9 @@ globalThis.addEventListener("DOMContentLoaded", () => { try { if (hash) { const [encodedMessage, encodedData, encodedLocale] = hash.split("."); - const message = atob(encodedMessage); - const data = atob(encodedData); - const locale = atob(encodedLocale); + const message = decode(encodedMessage); + const data = decode(encodedData); + const locale = decode(encodedLocale); messageArea.value = message; dataArea.value = data; localeSelect.value = locale; @@ -185,9 +186,9 @@ globalThis.addEventListener("DOMContentLoaded", () => { } } - const encodedMessage = btoa(messageArea.value); - const encodedData = btoa(dataArea.value); - const encodedLocale = btoa(localeSelect.value); + const encodedMessage = encode(messageArea.value); + const encodedData = encode(dataArea.value); + const encodedLocale = encode(localeSelect.value); const hash = `#${encodedMessage}.${encodedData}.${encodedLocale}` .replaceAll("/", "_").replaceAll("+", "-").replaceAll("=", ""); history.replaceState(null, "", hash);