# res-react-intl

[![Actions Status](https://github.com/SimonDegraeve/res-react-intl/workflows/res-react-intl%20pipeline/badge.svg)](https://github.com/SimonDegraeve/res-react-intl/actions)
[![NPM Version](https://badge.fury.io/js/res-react-intl.svg)](https://badge.fury.io/js/res-react-intl)

ReScript PPX generating [ReactIntl](https://github.com/formatjs/formatjs) `id` _(short MD5)_ from `defaultMessage`.

## Example

Input:

```rescript
// Demo.res
open ReactIntl

module Msg = {
  @@intl.messages
  let hello = {defaultMessage: "Hello"}
}

module Component1 = {
  @react.component
  let make = () => {
    <FormattedMessage defaultMessage="Some default message" />
  }
}
```

Output:

```js
// Demo.bs.js
// Generated by ReScript, PLEASE EDIT WITH CARE
'use strict'

let ReactIntl = require('react-intl')
let JsxRuntime = require('react/jsx-runtime')

let Msg_hello = {
  id: '_8b1a9953',
  defaultMessage: 'Hello',
}

let Msg = {
  hello: Msg_hello,
}

function Demo$Component1(props) {
  return JsxRuntime.jsx(ReactIntl.FormattedMessage, {
    id: '_0beb880a',
    defaultMessage: 'Some default message',
  })
}

let Component1 = {
  make: Demo$Component1,
}

exports.Msg = Msg
exports.Component1 = Component1
```

## Installation

### With `yarn` or `npm` on ReScript projects

Install the PPX with `yarn` or `npm`

```bash
yarn add res-react-intl bs-react-intl
# Or
npm install res-react-intl bs-react-intl
```

And add the PPX in your `rescript.json` (or `bsconfig.json`) file:

```json
{
  "bs-dependencies": ["bs-react-intl"],
  "ppx-flags": ["res-react-intl/ppx"]
}
```

Extract the messages:

```bash
res-react-intl-extract --allow-duplicates src
```

## Developing

### Setup (once)

Requires [opam](https://opam.ocaml.org/) and [yarn](https://yarnpkg.com/).

```bash
opam switch create . 4.14.2 --no-install --yes
eval $(opam env --switch=.)
opam install -y dune reason ocaml-migrate-parsetree yojson
cd test/rescript && yarn install && cd ../..
```

### Building the PPX

```bash
eval $(opam env --switch=.)
dune build
```

This produces `_build/default/bin/Ppx.exe` and `_build/default/bin/Extract.exe`.

### Running the integration test

```bash
cd test/rescript
yarn build          # compiles Demo.res through the PPX
git diff src/Demo.bs.js  # should be empty (output matches committed snapshot)
yarn extract        # runs Extract.exe --allow-duplicates src
```

### Dev loop

Edit `lib/Mapper.re` or `lib/Extractor.re`, then:

```bash
dune build && cd test/rescript && yarn build && git diff src/Demo.bs.js
```

### Releasing

1. Bump the version of the ppx in `esy.json` on `master` (we use [semantic versioning](https://semver.org/))
2. Create and push a new tag

```
$ git checkout master
$ git tag vx.y.z
$ git push origin vx.y.z
```

3. [Create detailed release notes](https://github.com/SimonDegraeve/res-react-intl/releases) for the new version, following the `Added/Changed/Fixed/Removed` format. Note that the new version of the PPX will automatically be pushed to NPM and a release will be created on GitHub.

## Background/Sources

- [Setup PPX Inspiration](https://github.com/dylanirlbeck/tailwind-ppx)
- [bs-react-intl-extractor](https://github.com/cknitt/bs-react-intl-extractor)
